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.
 
 
 
 
 
 

7086 lines
281 KiB

/*==========================================================================
*
* Copyright (C) 1994-1999 Microsoft Corporation. All Rights Reserved.
*
* File: ddgdi32.c
* Content: Contains the cross-process mapping layer similar to gdi32.dll
* on NT that the per-process DLL calls into on Win9X.
* History:
* Date By Reason
* ==== == ======
* 11-oct-99 smac initial implementation
*
***************************************************************************/
#include "ddrawpr.h"
#include "dx8priv.h"
#include "d3d8p.h"
#include "d3d8ddi.h"
#include "d3d8sddi.h"
#include "ddithunk.h"
extern HRESULT DDAPI DD_CreateSurface4_Main(LPDIRECTDRAW lpDD,LPDDSURFACEDESC2 lpDDSurfaceDesc,
LPDIRECTDRAWSURFACE FAR *lplpDDSurface,IUnknown FAR *pUnkOuter,BOOL bDoSurfaceDescCheck,
LPDDSURFACEINFO pSysMemInfo, DWORD DX8Flags);
extern void invalidateSurface(LPDDRAWI_DDRAWSURFACE_LCL this_lcl);
extern void makeDEVMODE(LPDDRAWI_DIRECTDRAW_GBL this, LPDDHALMODEINFO pmi, BOOL inexcl, BOOL useRefreshRate, LPDWORD pcds_flags, LPDEVMODE pdm);
void LoseDevice (DDDEVICEHANDLE* pDevice);
DDDEVICEHANDLE* pDeviceList = NULL;
// Bogus value used to initialize write only fields when communicating
// with the driver in debug builds
#define BOGUS_FIELD_VALUE 0xBAADCAFEul
typedef struct _KNOWNENTRY
{
DWORD PCIID;
DWORD VersionMajor; // 0 means all versions
DWORD VersionMinor; // 0 means all versions
DWORD Flags;
} KNOWNENTRY;
const KNOWNENTRY gKnownDeviceList[] =
{
// NVidia
{0x12D20018, 0, 0, KNOWN_ZSTENCILDEPTH}, // Riva 128
{0x10DE0020, 0, 0, KNOWN_LIGHTWEIGHT|KNOWN_D16_LOCKABLE|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // TNT
{0x10DE0028, 0, 0, KNOWN_LIGHTWEIGHT|KNOWN_D16_LOCKABLE|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // TNT2
{0x10DE0029, 0, 0, KNOWN_LIGHTWEIGHT|KNOWN_D16_LOCKABLE|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // TNT2 Ultra
{0x10DE002C, 0, 0, KNOWN_LIGHTWEIGHT|KNOWN_D16_LOCKABLE|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Vanta
{0x10DE002D, 0, 0, KNOWN_LIGHTWEIGHT|KNOWN_D16_LOCKABLE|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // TNT2 Model 64
{0x10DE00A0, 0, 0, KNOWN_LIGHTWEIGHT|KNOWN_D16_LOCKABLE|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Aladdin TNT2
{0x10DE0100, 0, 0, KNOWN_LIGHTWEIGHT|KNOWN_D16_LOCKABLE|KNOWN_MIPPEDCUBEMAPS|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // NV10 (GeForce)
{0x10DE0101, 0, 0, KNOWN_LIGHTWEIGHT|KNOWN_D16_LOCKABLE|KNOWN_MIPPEDCUBEMAPS|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // NV10 (GeForce DDR)
{0x10DE0103, 0, 0, KNOWN_LIGHTWEIGHT|KNOWN_D16_LOCKABLE|KNOWN_MIPPEDCUBEMAPS|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // NV10 (Quadro)
{0x10DE0110, 0, 0, KNOWN_LIGHTWEIGHT|KNOWN_D16_LOCKABLE|KNOWN_MIPPEDCUBEMAPS|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // NV11 (GeForce2 MX)
{0x10DE0111, 0, 0, KNOWN_LIGHTWEIGHT|KNOWN_D16_LOCKABLE|KNOWN_MIPPEDCUBEMAPS|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // NV11 (GeForce2 MX)
{0x10DE0113, 0, 0, KNOWN_LIGHTWEIGHT|KNOWN_D16_LOCKABLE|KNOWN_MIPPEDCUBEMAPS|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // NV11 (Quadro2 MXR)
{0x10DE0150, 0, 0, KNOWN_LIGHTWEIGHT|KNOWN_D16_LOCKABLE|KNOWN_MIPPEDCUBEMAPS|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // NV15 (GeForce2)
{0x10DE0151, 0, 0, KNOWN_LIGHTWEIGHT|KNOWN_D16_LOCKABLE|KNOWN_MIPPEDCUBEMAPS|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // NV15 (GeForce2 DDR)
{0x10DE0152, 0, 0, KNOWN_LIGHTWEIGHT|KNOWN_D16_LOCKABLE|KNOWN_MIPPEDCUBEMAPS|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // NV15 (GeForce2 BR)
{0x10DE0153, 0, 0, KNOWN_LIGHTWEIGHT|KNOWN_D16_LOCKABLE|KNOWN_MIPPEDCUBEMAPS|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // NV15 (Quadro2)
{0x10DE0200, 0, 0, KNOWN_LIGHTWEIGHT|KNOWN_D16_LOCKABLE|KNOWN_MIPPEDCUBEMAPS|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // NV20 (GeForce 3)
// 3DFX
{0x121A0003, 0, 0, KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_RTTEXTURE_R5G6B5}, // Banshee
{0x121A0005, 0, 0, KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_RTTEXTURE_R5G6B5}, // Voodoo3
{0x121a0009, 0, 0, KNOWN_CANMISMATCHRT|KNOWN_D16_LOCKABLE|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_A8R8G8B8}, // Voodoo4/5; same PCI-ID
// ATI
{0x10024742, 0, 0, KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_NOTAWINDOWEDBLTQUEUER|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // RagePro
{0x10024744, 0, 0, KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_NOTAWINDOWEDBLTQUEUER|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // RagePro
{0x10024749, 0, 0, KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_NOTAWINDOWEDBLTQUEUER|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // RagePro
{0x1002474D, 0, 0, KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_NOTAWINDOWEDBLTQUEUER|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // RagePro
{0x1002474E, 0, 0, KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_NOTAWINDOWEDBLTQUEUER|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // RagePro
{0x1002474F, 0, 0, KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_NOTAWINDOWEDBLTQUEUER|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // RagePro
{0x10024750, 0, 0, KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_NOTAWINDOWEDBLTQUEUER|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // RagePro
{0x10024752, 0, 0, KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_NOTAWINDOWEDBLTQUEUER|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // RagePro
{0x10024C42, 0, 0, KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_NOTAWINDOWEDBLTQUEUER|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // RagePro (PCI)
{0x10024C49, 0, 0, KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_NOTAWINDOWEDBLTQUEUER|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // RagePro (PCI)
{0x10024C4E, 0, 0, KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_NOTAWINDOWEDBLTQUEUER|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // RagePro
{0x10024C52, 0, 0, KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_NOTAWINDOWEDBLTQUEUER|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // RagePro
{0x10024C53, 0, 0, KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_NOTAWINDOWEDBLTQUEUER|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // RagePro
{0x10024C60, 0, 0, KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_NOTAWINDOWEDBLTQUEUER|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // RagePro LT
{0x10024C4D, 0, 0, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_NOTAWINDOWEDBLTQUEUER|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X1R5G5B5}, // Rage Mobility AGP
{0x10024C46, 0x0004000c, 0x00010411, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage Mobility 128
{0x10024C46, 0, 0, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage Mobility 128
{0x10024D46, 0x0004000c, 0x00010411, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage Mobility 128
{0x10024D46, 0, 0, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage Mobility 128
{0x10025046, 0x0004000c, 0x00011f43, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO AGP 4X TMDS
{0x10025046, 0, 0, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO AGP 4X TMDS
{0x10025245, 0x0004000c, 0x00011f43, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128
{0x10025245, 0, 0, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128
{0x10025246, 0x0004000c, 0x00011f43, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128
{0x10025246, 0, 0, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128
{0x1002524B, 0x0004000c, 0x00011f43, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 VR PCI //DX8.1
{0x1002524B, 0, 0, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 VR PCI //DX8.1
{0x1002524C, 0x0004000c, 0x00011f43, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128
{0x1002524C, 0, 0, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128
//New 128s for DX8.1:
{0x10025041, 0x0004000c, 0x00011f43, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO PCI DX8.1
{0x10025041, 0, 0, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO PCI DX8.1
{0x10025042, 0x0004000c, 0x00011f43, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO AGP 2X DX8.1
{0x10025042, 0, 0, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO AGP 2X DX8.1
{0x10025043, 0x0004000c, 0x00011f43, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO AGP 4X DX8.1
{0x10025043, 0, 0, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO AGP 4X DX8.1
{0x10025044, 0x0004000c, 0x00011f43, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO PCI TMDS DX8.1
{0x10025044, 0, 0, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO PCI TMDS DX8.1
{0x10025045, 0x0004000c, 0x00011f43, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO AGP 2X TMDS DX8.1
{0x10025045, 0, 0, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO AGP 2X TMDS DX8.1
{0x10025047, 0x0004000c, 0x00011f43, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO PCI DX8.1
{0x10025047, 0, 0, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO PCI DX8.1
{0x10025048, 0x0004000c, 0x00011f43, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO AGP 2X DX8.1
{0x10025048, 0, 0, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO AGP 2X DX8.1
{0x10025049, 0x0004000c, 0x00011f43, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO AGP 4X DX8.1
{0x10025049, 0, 0, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO AGP 4X DX8.1
{0x1002504a, 0x0004000c, 0x00011f43, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO PCI TMDS DX8.1
{0x1002504a, 0, 0, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO PCI TMDS DX8.1
{0x1002504b, 0x0004000c, 0x00011f43, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO AGP 2X TMDS DX8.1
{0x1002504b, 0, 0, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO AGP 2X TMDS DX8.1
{0x1002504c, 0x0004000c, 0x00011f43, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO AGP 4X TMDS DX8.1
{0x1002504c, 0, 0, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO AGP 4X TMDS DX8.1
{0x1002504d, 0x0004000c, 0x00011f43, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO AGP DX8.1
{0x1002504d, 0, 0, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO AGP DX8.1
{0x1002504e, 0x0004000c, 0x00011f43, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO AGP 2X DX8.1
{0x1002504e, 0, 0, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO AGP 2X DX8.1
{0x1002504f, 0x0004000c, 0x00011f43, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO AGP 4X DX8.1
{0x1002504f, 0, 0, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO AGP 4X DX8.1
{0x10025050, 0x0004000c, 0x00011f43, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO PCI TMDS DX8.1
{0x10025050, 0, 0, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO PCI TMDS DX8.1
{0x10025051, 0x0004000c, 0x00011f43, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO AGP 2X TMDS DX8.1
{0x10025051, 0, 0, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO AGP 2X TMDS DX8.1
{0x10025052, 0x0004000c, 0x00011f43, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO AGP 4X TMDS DX8.1
{0x10025052, 0, 0, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO AGP 4X TMDS DX8.1
{0x10025053, 0x0004000c, 0x00011f43, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO PCI DX8.1
{0x10025053, 0, 0, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO PCI DX8.1
{0x10025054, 0x0004000c, 0x00011f43, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO AGP 2X DX8.1
{0x10025054, 0, 0, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO AGP 2X DX8.1
{0x10025055, 0x0004000c, 0x00011f43, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO AGP 4X DX8.1
{0x10025055, 0, 0, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO AGP 4X DX8.1
{0x10025056, 0x0004000c, 0x00011f43, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO PCI TMDS DX8.1
{0x10025056, 0, 0, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO PCI TMDS DX8.1
{0x10025057, 0x0004000c, 0x00011f43, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO AGP 2X TMDS DX8.1
{0x10025057, 0, 0, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO AGP 2X TMDS DX8.1
{0x10025058, 0x0004000c, 0x00011f43, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO AGP 4X TMDS DX8.1
{0x10025058, 0, 0, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO AGP 4X TMDS DX8.1
{0x10025345, 0x0004000c, 0x00011f43, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 4X PCI DX8.1
{0x10025345, 0, 0, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 4X PCI DX8.1
{0x10025346, 0x0004000c, 0x00011f43, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 4X AGP 2X DX8.1
{0x10025346, 0, 0, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 4X AGP 2X DX8.1
{0x10025347, 0x0004000c, 0x00011f43, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 4X AGP 4X DX8.1
{0x10025347, 0, 0, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 4X AGP 4X DX8.1
{0x10025348, 0x0004000c, 0x00011f43, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 4X DX8.1
{0x10025348, 0, 0, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 4X DX8.1
{0x1002534b, 0x0004000c, 0x00011f43, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 4X PCI DX8.1
{0x1002534b, 0, 0, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 4X PCI DX8.1
{0x1002534c, 0x0004000c, 0x00011f43, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 4X AGP 2X DX8.1
{0x1002534c, 0, 0, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 4X AGP 2X DX8.1
{0x1002534d, 0x0004000c, 0x00011f43, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 4X AGP 4X DX8.1
{0x1002534d, 0, 0, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 4X AGP 4X DX8.1
{0x1002534e, 0x0004000c, 0x00011f43, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 4X DX8.1
{0x1002534e, 0, 0, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 4X DX8.1
{0x10025446, 0x0004000c, 0x00011f43, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO ULTRA GL AGP DX8.1
{0x10025446, 0, 0, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO ULTRA GL AGP DX8.1
{0x1002544c, 0x0004000c, 0x00011f43, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO ULTRA VR AGP DX8.1
{0x1002544c, 0, 0, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO ULTRA VR AGP DX8.1
{0x10025452, 0x0004000c, 0x00011f43, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO ULTRA4XL VR-R AGP DX8.1
{0x10025452, 0, 0, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage128 PRO ULTRA4XL VR-R AGP DX8.1
{0x10025144, 0, 0, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage6
{0x10025145, 0, 0, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage6
{0x10025146, 0, 0, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage6
{0x10025147, 0, 0, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Rage6
// Intel
{0x80867800, 0, 0, KNOWN_ZSTENCILDEPTH|KNOWN_NOTAWINDOWEDBLTQUEUER}, // Intel i740
{0x80867123, 0, 0, KNOWN_ZSTENCILDEPTH|KNOWN_NOTAWINDOWEDBLTQUEUER|KNOWN_RTTEXTURE_R5G6B5}, // Intel 810
{0x80867125, 0, 0, KNOWN_ZSTENCILDEPTH|KNOWN_NOTAWINDOWEDBLTQUEUER|KNOWN_RTTEXTURE_R5G6B5}, // Intel 810e
{0x80861132, 0, 0, KNOWN_ZSTENCILDEPTH|KNOWN_NOTAWINDOWEDBLTQUEUER|KNOWN_RTTEXTURE_R5G6B5}, // Intel 815
{0x80861A12, 0, 0, KNOWN_ZSTENCILDEPTH|KNOWN_NOTAWINDOWEDBLTQUEUER}, // Intel Timna
// Matrox
{0x102b0520, 0x0004000b, 0x000110ea, KNOWN_ZSTENCILDEPTH|KNOWN_CANMISMATCHRT|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // G200 PCI
{0x102b0520, 0, 0, KNOWN_ZSTENCILDEPTH}, // G200 PCI
{0x102b0521, 0x0004000b, 0x000110ea, KNOWN_ZSTENCILDEPTH|KNOWN_CANMISMATCHRT|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // G200 AGP
{0x102b0521, 0, 0, KNOWN_ZSTENCILDEPTH}, // G200 AGP
{0x102b0525, 0x0004000b, 0x000110ea, KNOWN_ZSTENCILDEPTH|KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // G400, G450
{0x102b0525, 0, 0, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // G400, G450
// 3DLabs
{0x3d3d0008, 0, 0, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH}, // 3DLabs Gamma
{0x104c3d07, 0, 0, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8}, // Perm2
{0x3d3d0009, 0, 0, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8}, // Perm2
{0x3d3d000a, 0, 0, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Perm3
{0x3d3d000c, 0, 0, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Perm3
// Videologic
{0x104a0010, 0x0004000c, 0x0001080c, KNOWN_ZSTENCILDEPTH|KNOWN_CANMISMATCHRT|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // PowerVR Kyro updated driver
{0x104a0010, 0, 0, KNOWN_ZSTENCILDEPTH}, // PowerVR Kyro
// S3
{0x53338811, 0, 0, KNOWN_ZSTENCILDEPTH|KNOWN_NOTAWINDOWEDBLTQUEUER|KNOWN_RTTEXTURE_X1R5G5B5}, // Virge
{0x53335631, 0, 0, KNOWN_ZSTENCILDEPTH|KNOWN_NOTAWINDOWEDBLTQUEUER|KNOWN_RTTEXTURE_X1R5G5B5}, // Virge
{0x53338a01, 0, 0, KNOWN_ZSTENCILDEPTH|KNOWN_NOTAWINDOWEDBLTQUEUER|KNOWN_RTTEXTURE_X1R5G5B5}, // Virge DX/GX DX8.1
{0x53338c01, 0, 0, KNOWN_ZSTENCILDEPTH|KNOWN_NOTAWINDOWEDBLTQUEUER|KNOWN_RTTEXTURE_X1R5G5B5}, // Virge MX DX8.1
{0x53338a10, 0, 0, KNOWN_ZSTENCILDEPTH|KNOWN_NOTAWINDOWEDBLTQUEUER|KNOWN_RTTEXTURE_X1R5G5B5}, // Virge GX2 DX8.1
{0x53338a20, 0, 0, KNOWN_ZSTENCILDEPTH|KNOWN_NOTAWINDOWEDBLTQUEUER}, // Savage3D
{0x53338a22, 0, 0, KNOWN_ZSTENCILDEPTH|KNOWN_NOTAWINDOWEDBLTQUEUER|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Savage4
{0x53339102, 0, 0, KNOWN_ZSTENCILDEPTH|KNOWN_NOTAWINDOWEDBLTQUEUER}, // Savage2K
{0x53338c10, 0, 0, KNOWN_ZSTENCILDEPTH|KNOWN_CANMISMATCHRT|KNOWN_RTTEXTURE_R5G6B5}, // Savage MX DX8.1
{0x53338c12, 0, 0, KNOWN_ZSTENCILDEPTH|KNOWN_CANMISMATCHRT|KNOWN_RTTEXTURE_R5G6B5}, // Savage IX DX8.1
{0x53338a25, 0, 0, KNOWN_ZSTENCILDEPTH|KNOWN_CANMISMATCHRT|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Savage Pro DX8.1
{0x53338a26, 0, 0, KNOWN_ZSTENCILDEPTH|KNOWN_CANMISMATCHRT|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Savage Pro DX8.1
// Trident
{0x10239880, 0, 0, KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_NOTAWINDOWEDBLTQUEUER}, // Trident Blade 3D 9880
{0x10238500, 0, 0, KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_NOTAWINDOWEDBLTQUEUER|KNOWN_CANMISMATCHRT|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Trident Blade 3D/ProMedia DX8.1
{0x10238400, 0, 0, KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_NOTAWINDOWEDBLTQUEUER|KNOWN_CANMISMATCHRT|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Trident Blade 3D/MVP4 DX8.1
{0x10238420, 0, 0, KNOWN_ZSTENCILDEPTH|KNOWN_NOTAWINDOWEDBLTQUEUER|KNOWN_CANMISMATCHRT|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Trident CyberBlade i7
{0x10239910, 0, 0, KNOWN_ZSTENCILDEPTH|KNOWN_NOTAWINDOWEDBLTQUEUER|KNOWN_CANMISMATCHRT|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Trident CyberBlade DX8.1
// SiS
{0x10390300, 0, 0, KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_R5G6B5}, // SiS 300
{0x10390300, 0x0004000d, 0x000107da, KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_CANMISMATCHRT|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // SiS 300
{0x10395300, 0x0004000d, 0x000107da, KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_CANMISMATCHRT|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // SiS 300
{0x10396326, 0, 0, KNOWN_ZSTENCILDEPTH|KNOWN_NOTAWINDOWEDBLTQUEUER}, // SiS 6326
{0x10396300, 0, 0, KNOWN_ZSTENCILDEPTH|KNOWN_CANMISMATCHRT|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_R5G6B5}, // SiS 6300
{0x10396300, 0x0004000d, 0x000107da, KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_CANMISMATCHRT|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // SiS 6300
{0x10390310, 0x0004000d, 0x00010352, KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_CANMISMATCHRT|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // SiS 6300
{0x10390315, 0x0004000d, 0x00010352, KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_CANMISMATCHRT|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // SiS 6300
{0x10390325, 0x0004000c, 0x000107d3, KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_CANMISMATCHRT|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // SiS 6300
{0x10396325, 0x0004000c, 0x000107d3, KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_CANMISMATCHRT|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // SiS 640/740
{0x126f0720, 0, 0, KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_A1R5G5B5} //Silicon Motion Lynx3DM
};
#define NUM_KNOWN_DEVICES (sizeof(gKnownDeviceList)/sizeof(KNOWNENTRY))
#define CACHE_GROW_SIZE 30
#define RESPATH_D3D "Software\\Microsoft\\Direct3D"
// Minimum size of DrawPrimitive buffer associated with a context.
#define MIN_PRIM_BUFFER_SIZE (1 << 14)
// Maximum
#define MAX_PRIM_BUFFER_SIZE (1 << 20)
// Default
#define DEF_PRIM_BUFFER_SIZE (1 << 16)
const DWORD dwOrderedFaces[6] = {
DDSCAPS2_CUBEMAP_POSITIVEX,
DDSCAPS2_CUBEMAP_NEGATIVEX,
DDSCAPS2_CUBEMAP_POSITIVEY,
DDSCAPS2_CUBEMAP_NEGATIVEY,
DDSCAPS2_CUBEMAP_POSITIVEZ,
DDSCAPS2_CUBEMAP_NEGATIVEZ
};
__inline LPDDRAWI_DDRAWSURFACE_INT GetHeavyweightSurf(DDSURFACE* pSurf)
{
return (pSurf->dwFlags & DDSURFACE_LIGHTWEIGHT) ? MapLightweightSurface(pSurf) : pSurf->Surface.pHeavy;
}
#define DONE_HEAVYWEIGHT_SURF(x) \
if (((PDDSURFACE)(x))->dwFlags & DDSURFACE_LIGHTWEIGHT) \
UnmapLightweightSurface(x)
HRESULT MapLegacyResult(HRESULT in)
{
HRESULT hr;
switch (in)
{
case DD_OK:
hr = S_OK;
break;
case DDERR_OUTOFVIDEOMEMORY:
hr = D3DERR_OUTOFVIDEOMEMORY;
break;
case DDERR_CURRENTLYNOTAVAIL:
case DDERR_UNSUPPORTED:
hr = D3DERR_NOTAVAILABLE;
break;
case DDERR_OUTOFMEMORY:
hr = E_OUTOFMEMORY;
break;
default:
hr = D3DERR_DRIVERINTERNALERROR;
}
return hr;
}
BOOL FormatCompatibleWithDisplayFormat(
PDDDEVICEHANDLE pDD,
D3DFORMAT Format)
{
return (BOOL) (Format == pDD->DisplayFormatWithAlpha);
}
HRESULT LockDibEngine(LPDDRAWI_DIRECTDRAW_GBL pdrv)
{
HRESULT ret;
LPWORD pdflags;
BOOL isbusy;
pdflags = pdrv->lpwPDeviceFlags;
isbusy = 0;
_asm
{
mov eax, pdflags
bts word ptr [eax], BUSY_BIT
adc isbusy,0
}
if (isbusy && (0 == pdrv->dwWin16LockCnt))
{
D3D_WARN(2, "LOCK_DIBENGINE, dibengine is busy");
ret = DDERR_SURFACEBUSY;
} else
ret = DD_OK;
return ret;
}
void UnlockDibEngine(LPDDRAWI_DIRECTDRAW_GBL pdrv)
{
if (0 == pdrv->dwWin16LockCnt)
{
*pdrv->lpwPDeviceFlags &= ~BUSY;
}
}
#define CALL_D3DHAL_TAKEBUSY_NOWIN16(ret, pDevice, func, data) \
{ \
if (func) \
{ \
ret = LockDibEngine((pDevice)->pDD->lpLcl->lpGbl); \
if (ret != DD_OK) \
{ \
ret = DDHAL_DRIVER_HANDLED; \
} \
else \
{ \
ret = (*(func))(data); \
UnlockDibEngine((pDevice)->pDD->lpLcl->lpGbl); \
} \
} \
else \
{ \
DPF_ERR("No HAL call available"); \
ret = DDHAL_DRIVER_NOTHANDLED; \
} \
}
#define CALL_D3DHAL_TAKEBUSY_TAKEWIN16(ret, pDevice, func, data) \
{ \
ENTER_WIN16LOCK(); \
CALL_D3DHAL_TAKEBUSY_NOWIN16(ret, pDevice, func, data); \
LEAVE_WIN16LOCK(); \
}
BOOL CanKnownDriverDoThis(PDDDEVICEHANDLE pDevice, DWORD Flag)
{
BOOL ret = FALSE;
int i;
if (pDevice->ForceFlagsOff & Flag)
{
return FALSE;
}
else if (pDevice->ForceFlagsOn & Flag)
{
return TRUE;
}
// Only drivers in our known good list can support lightweight
// surfaces
if (pDevice->PCIID == 0)
{
DDDEVICEIDENTIFIER2 DI;
if (InternalGetDeviceIdentifier7( (LPDIRECTDRAW) pDevice->pDD, &DI, 0, FALSE) == DD_OK)
{
pDevice->PCIID = (DI.dwVendorId << 16) | DI.dwDeviceId;
pDevice->DriverVersionHigh = DI.liDriverVersion.HighPart;
pDevice->DriverVersionLow = DI.liDriverVersion.LowPart;
}
}
for (i = 0; i < NUM_KNOWN_DEVICES; i++)
{
if ((gKnownDeviceList[i].PCIID == pDevice->PCIID) &&
(gKnownDeviceList[i].Flags & Flag) &&
((pDevice->DriverVersionHigh > gKnownDeviceList[i].VersionMajor) ||
((pDevice->DriverVersionHigh == gKnownDeviceList[i].VersionMajor) &&
(pDevice->DriverVersionLow >= gKnownDeviceList[i].VersionMinor))))
{
ret = TRUE;
break;
}
}
return ret;
}
BOOL IsLightweightSurface(PDDDEVICEHANDLE pDevice, DDSURFACEDESC2* pddsd2, D3DFORMAT Format)
{
// Render targets, Z buffers, cursor surfaces, and any part of flip chain
// must remain heavyweight surfaces.
if (pddsd2->ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE |
DDSCAPS_3DDEVICE |
DDSCAPS_ZBUFFER |
DDSCAPS_OFFSCREENPLAIN))
{
return FALSE;
}
// All paletized textures must be heavyweight unless it's at least a DX8
// driver. This is because some DX7 drivers don't handle palettes right.
if ((pDevice->DriverLevel < 8) &&
((Format == D3DFMT_A8P8) || (Format == D3DFMT_P8)))
{
return FALSE;
}
if (pddsd2->ddsCaps.dwCaps2 & DDSCAPS2_VOLUME)
{
return FALSE;
}
// If it's a static VB or IB, then we can let that be lightweight
if ((pDevice->DriverLevel >= 8) &&
(pddsd2->ddsCaps.dwCaps2 & DDSCAPS_EXECUTEBUFFER) &&
(pddsd2->ddsCaps.dwCaps2 & DDSCAPS2_HINTSTATIC))
{
return TRUE;
}
// Unless it's static, the runtime locks vidmem vbs indefinately,
// so if we make them lightweight they will fill up our cache table
// with 1000s of entries. Therefore, we will make them heavyweight.
if ((pddsd2->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER) &&
(pddsd2->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
{
return FALSE;
}
// Dynamic textures will be frequently locked, so it is inefficient
// to make them light weight.
if ((pddsd2->ddsCaps.dwCaps2 & DDSCAPS2_HINTDYNAMIC) &&
(pddsd2->ddsCaps.dwCaps & DDSCAPS_TEXTURE) &&
(pddsd2->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
{
return FALSE;
}
return TRUE;
}
void UpdateSurfaceCache(DDSURFACE* pSurf)
{
LPDDRAWI_DDRAWSURFACE_LCL pLcl = GET_CACHED_LIGHTWEIGHT_INT(pSurf)->lpLcl;
LPDDRAWI_DDRAWSURFACE_GBL_MORE lpGblMore;
// Update those fields in the lightweight structure that the driver may
// have changed
pSurf->Surface.pLight->GblFlags = pLcl->lpGbl->dwGlobalFlags;
pSurf->Surface.pLight->fpGblVidMem = pLcl->lpGbl->fpVidMem;
pSurf->Surface.pLight->GblPitch = pLcl->lpGbl->lPitch;
pSurf->Surface.pLight->GblReserved1 = pLcl->lpGbl->dwReserved1;
pSurf->Surface.pLight->LclFlags = pLcl->dwFlags;
pSurf->Surface.pLight->LclCaps1 = pLcl->ddsCaps.dwCaps;
pSurf->Surface.pLight->LclReserved1 = pLcl->dwReserved1;
lpGblMore = GET_LPDDRAWSURFACE_GBL_MORE (pLcl->lpGbl);
pSurf->Surface.pLight->GblMoreDriverReserved = lpGblMore->dwDriverReserved;
pSurf->Surface.pLight->GblMoreContentsStamp = lpGblMore->dwContentsStamp;
pSurf->Surface.pLight->pGblMoreUnswappedDriverReserved = lpGblMore->lpvUnswappedDriverReserved;
pSurf->Surface.pLight->fpGblMoreAliasOfVidMem = lpGblMore->fpAliasOfVidMem;
pSurf->Surface.pLight->cGblMorePageUnlocks = lpGblMore->cPageUnlocks;
if (pSurf->Surface.pLight->LclCaps1 & DDSCAPS_LOCALVIDMEM)
{
pSurf->Surface.pLight->fpGblMoreAliasedVidMem = lpGblMore->fpAliasedVidMem;
}
else if (pSurf->Surface.pLight->LclCaps1 & DDSCAPS_NONLOCALVIDMEM)
{
pSurf->Surface.pLight->fpGblMorePhysicalVidMem = lpGblMore->fpPhysicalVidMem;
}
}
LPDDRAWI_DDRAWSURFACE_INT MapLightweightSurface(DDSURFACE* pSurf)
{
LPDDRAWI_DDRAWSURFACE_INT pCached = NULL;
PDDDEVICEHANDLE pDevice = pSurf->pDevice;
int i;
LPDDRAWI_DDRAWSURFACE_GBL_MORE* ppGblMore;
DWORD Lowest;
DWORD LowestEntry;
CACHEENTRY* pCachedEntry = NULL;
UINT CacheIndex;
// If the surface is already mapped, this is pretty easy
if (pSurf->Surface.pLight->CachedIndex)
{
DDASSERT(pSurf->Surface.pLight->CachedIndex & INDEX_IN_USE);
pCachedEntry = GET_CACHED_ENTRY(pSurf);
pCachedEntry->pSurface->dwReserved2++; // up the ref count
pCachedEntry->UsageStamp = pDevice->CacheUsageStamp++;
// Protect against wrap around of the usage stamp
if (pDevice->CacheUsageStamp == 0)
{
for (i = 0; i < pDevice->NumCachedSurfaces; i++)
{
pDevice->pCachedSurfaceTable[i].UsageStamp = 0;
}
}
return pCachedEntry->pSurface;
}
// Otherwise, find an available surface to use
do
{
// Look through the list and look for either a surface that isn't being used,
// or one that we can use with the lowest UsageStamp.
Lowest = LowestEntry = (DWORD) -1;
for (i = 0; i < pDevice->NumCachedSurfaces; i++)
{
if (pDevice->pCachedSurfaceTable[i].pSurface->dwReserved1 == (ULONG_PTR) NULL)
{
pCachedEntry = &(pDevice->pCachedSurfaceTable[i]);
CacheIndex = i;
break;
}
else if ((pDevice->pCachedSurfaceTable[i].pSurface->dwReserved2 == 0) &&
(pDevice->pCachedSurfaceTable[i].UsageStamp < Lowest))
{
Lowest = pDevice->pCachedSurfaceTable[i].UsageStamp;
LowestEntry = (DWORD) i;
}
}
if ((pCachedEntry == NULL) && (LowestEntry != (DWORD) -1))
{
// We don't have an empty one, but we found one that we can flush
UpdateSurfaceCache((DDSURFACE*)(pDevice->pCachedSurfaceTable[LowestEntry].pSurface->dwReserved1));
((DDSURFACE*)(pDevice->pCachedSurfaceTable[LowestEntry].pSurface->dwReserved1))->Surface.pLight->CachedIndex = 0;
pDevice->pCachedSurfaceTable[LowestEntry].pSurface->dwReserved1 = (ULONG_PTR) NULL;
pCachedEntry = &(pDevice->pCachedSurfaceTable[LowestEntry]);
CacheIndex = LowestEntry;
}
if (pCachedEntry == NULL)
{
// If we still can't find one, then we need to grow the table
int NewNum;
CACHEENTRY* pNewTable;
NewNum = pDevice->NumCachedSurfaces + CACHE_GROW_SIZE;
pNewTable = (CACHEENTRY*) MemAlloc(sizeof(CACHEENTRY) * NewNum);
if (pNewTable == NULL)
{
return NULL;
}
for (i = 0; i < pDevice->NumCachedSurfaces; i++)
{
pNewTable[i] = pDevice->pCachedSurfaceTable[i];
}
while (i < NewNum)
{
pNewTable[i].UsageStamp = 0;
pNewTable[i].pSurface = (LPDDRAWI_DDRAWSURFACE_INT)
MemAlloc(sizeof(DDRAWI_DDRAWSURFACE_INT) +
sizeof(DDRAWI_DDRAWSURFACE_LCL) +
sizeof(DDRAWI_DDRAWSURFACE_GBL) +
sizeof(DDRAWI_DDRAWSURFACE_MORE) +
sizeof(DDRAWI_DDRAWSURFACE_GBL_MORE) +
sizeof(LPDDRAWI_DDRAWSURFACE_GBL_MORE));
if (pNewTable[i].pSurface == NULL)
{
break;
}
else
{
i++;
}
}
if (pDevice->pCachedSurfaceTable != NULL)
{
MemFree(pDevice->pCachedSurfaceTable);
}
pDevice->NumCachedSurfaces = i;
pDevice->pCachedSurfaceTable = pNewTable;
}
} while (pCachedEntry == NULL);
pCachedEntry->UsageStamp = pDevice->CacheUsageStamp++;
// Protect against wrap around of the usage stamp
if (pDevice->CacheUsageStamp == 0)
{
for (i = 0; i < pDevice->NumCachedSurfaces; i++)
{
pDevice->pCachedSurfaceTable[i].UsageStamp = 0;
}
}
// We have the memory that we want to use, so now we need to initialze it
pCached = pCachedEntry->pSurface;
memset(pCached, 0, sizeof(DDRAWI_DDRAWSURFACE_INT) +
sizeof(DDRAWI_DDRAWSURFACE_LCL) +
sizeof(DDRAWI_DDRAWSURFACE_GBL) +
sizeof(DDRAWI_DDRAWSURFACE_MORE) +
sizeof(DDRAWI_DDRAWSURFACE_GBL_MORE) +
sizeof(LPDDRAWI_DDRAWSURFACE_GBL_MORE));
pCached->dwReserved1 = (ULONG_PTR) pSurf;
pCached->dwReserved2 = 1; // Init the ref count
pSurf->Surface.pLight->CachedIndex = CacheIndex | INDEX_IN_USE; // So a used entry is never 0
pCached->lpLcl = (LPDDRAWI_DDRAWSURFACE_LCL)
(((BYTE*)pCached) + sizeof(DDRAWI_DDRAWSURFACE_INT));
pCached->lpLcl->lpSurfMore = (LPDDRAWI_DDRAWSURFACE_MORE)
(((BYTE*)pCached) + sizeof(DDRAWI_DDRAWSURFACE_INT) +
sizeof(DDRAWI_DDRAWSURFACE_LCL));
pCached->lpLcl->lpGbl = (LPDDRAWI_DDRAWSURFACE_GBL)
(((BYTE*)pCached) + sizeof(DDRAWI_DDRAWSURFACE_INT) +
sizeof(DDRAWI_DDRAWSURFACE_LCL) +
sizeof(DDRAWI_DDRAWSURFACE_MORE) +
sizeof(LPDDRAWI_DDRAWSURFACE_GBL_MORE));
ppGblMore = (LPDDRAWI_DDRAWSURFACE_GBL_MORE*) ((BYTE*)(pCached->lpLcl->lpGbl) -
sizeof(LPDDRAWI_DDRAWSURFACE_GBL_MORE));
*ppGblMore = (LPDDRAWI_DDRAWSURFACE_GBL_MORE)
(((BYTE*)pCached) + sizeof(DDRAWI_DDRAWSURFACE_INT) +
sizeof(DDRAWI_DDRAWSURFACE_LCL) +
sizeof(DDRAWI_DDRAWSURFACE_MORE) +
sizeof(LPDDRAWI_DDRAWSURFACE_GBL_MORE) +
sizeof(DDRAWI_DDRAWSURFACE_GBL));
// Now fill it in with the meaningful data
pCached->lpLcl->dwFlags = pSurf->Surface.pLight->LclFlags;
pCached->lpLcl->ddsCaps.dwCaps = pSurf->Surface.pLight->LclCaps1;
pCached->lpLcl->dwReserved1 = pSurf->Surface.pLight->LclReserved1;
pCached->lpLcl->dwModeCreatedIn = pSurf->Surface.pLight->LclModeCreatedIn;
pCached->lpLcl->dwBackBufferCount = pSurf->Surface.pLight->LclBackBufferCount;
pCached->lpLcl->dwProcessId = pDevice->PID;
pCached->lpLcl->lpGbl->dwGlobalFlags = pSurf->Surface.pLight->GblFlags;
pCached->lpLcl->lpGbl->lPitch = pSurf->Surface.pLight->GblPitch;
pCached->lpLcl->lpGbl->wWidth = (WORD) pSurf->Surface.pLight->GblWidth;
pCached->lpLcl->lpGbl->wHeight = (WORD) pSurf->Height;
pCached->lpLcl->lpGbl->dwReserved1 = pSurf->Surface.pLight->GblReserved1;
if (pSurf->Surface.pLight->GblFormat != D3DFMT_UNKNOWN)
{
ConvertToOldFormat(&pCached->lpLcl->lpGbl->ddpfSurface,
pSurf->Surface.pLight->GblFormat);
}
pCached->lpLcl->lpGbl->lpVidMemHeap = pSurf->Surface.pLight->pGblVidMemHeap;
pCached->lpLcl->lpGbl->fpVidMem = pSurf->Surface.pLight->fpGblVidMem;
pCached->lpLcl->lpSurfMore->ddsCapsEx.dwCaps2 = pSurf->Surface.pLight->MoreCaps2;
pCached->lpLcl->lpSurfMore->ddsCapsEx.dwCaps3 = pSurf->Surface.pLight->MoreCaps3;
pCached->lpLcl->lpSurfMore->ddsCapsEx.dwCaps4 = pSurf->Surface.pLight->MoreCaps4;
pCached->lpLcl->lpSurfMore->rgjunc = pSurf->Surface.pLight->MoreRgjunc;
pCached->lpLcl->lpSurfMore->dwSurfaceHandle = pSurf->dwCookie;
if (IS_SOFTWARE_DRIVER_SURFACE(pSurf))
{
pCached->lpLcl->lpSurfMore->lpDD_lcl = pDevice->pSwDD->lpLcl;
pCached->lpLcl->lpSurfMore->lpDD_int = pDevice->pSwDD;
pCached->lpLcl->lpGbl->lpDD = pDevice->pSwDD->lpLcl->lpGbl;
}
else
{
pCached->lpLcl->lpSurfMore->lpDD_lcl = pDevice->pDD->lpLcl;
pCached->lpLcl->lpSurfMore->lpDD_int = pDevice->pDD;
pCached->lpLcl->lpGbl->lpDD = pDevice->pDD->lpLcl->lpGbl;
}
(*ppGblMore)->dwDriverReserved = pSurf->Surface.pLight->GblMoreDriverReserved;
(*ppGblMore)->dwContentsStamp = pSurf->Surface.pLight->GblMoreContentsStamp;
(*ppGblMore)->lpvUnswappedDriverReserved = pSurf->Surface.pLight->pGblMoreUnswappedDriverReserved;
(*ppGblMore)->fpAliasOfVidMem = pSurf->Surface.pLight->fpGblMoreAliasOfVidMem;
(*ppGblMore)->cPageUnlocks = pSurf->Surface.pLight->cGblMorePageUnlocks;
if (pCached->lpLcl->ddsCaps.dwCaps & DDSCAPS_MIPMAP)
{
pCached->lpLcl->lpSurfMore->dwMipMapCount = pSurf->Surface.pLight->MoreMipMapCount;
}
else
{
pCached->lpLcl->lpSurfMore->dwFVF = pSurf->Surface.pLight->MoreFVF;
}
if (pCached->lpLcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
{
pCached->lpLcl->lpSurfMore->dwBytesAllocated = pSurf->Surface.pLight->MoreBytesAllocated;
}
else if (pCached->lpLcl->ddsCaps.dwCaps & DDSCAPS_NONLOCALVIDMEM)
{
(*ppGblMore)->fpPhysicalVidMem = pSurf->Surface.pLight->fpGblMorePhysicalVidMem;
}
else if (pCached->lpLcl->ddsCaps.dwCaps & DDSCAPS_LOCALVIDMEM)
{
(*ppGblMore)->fpAliasedVidMem = pSurf->Surface.pLight->fpGblMoreAliasedVidMem;
}
pCached->lpVtbl = (LPVOID) &ddSurface7Callbacks;
return pCached;
}
void UnmapLightweightSurface(DDSURFACE* pSurf)
{
DDASSERT(pSurf->Surface.pLight->CachedIndex & INDEX_IN_USE);
DDASSERT(pSurf->dwFlags & DDSURFACE_LIGHTWEIGHT);
DDASSERT(GET_CACHED_ENTRY(pSurf)->pSurface->dwReserved2 > 0);
if (--(GET_CACHED_ENTRY(pSurf)->pSurface->dwReserved2) == 0)
{
// Vertex and command buffers are used by DP2, so we want to optimize
// for them. Even though we are done using the surface, we will keep
// the heavyweight surface around so we can use it again quickly if
// we need to.
if (!(pSurf->Surface.pLight->LclCaps1 & DDSCAPS_EXECUTEBUFFER))
{
UpdateSurfaceCache(pSurf);
GET_CACHED_ENTRY(pSurf)->pSurface->dwReserved1 = (ULONG_PTR) NULL;
pSurf->Surface.pLight->CachedIndex = 0;
}
}
}
void ReleaseDX7SurfaceHandle(HANDLE hDD, DWORD handle)
{
PDDDEVICEHANDLE pDeviceHandle = (PDDDEVICEHANDLE) hDD;
pDeviceHandle->SurfaceHandleList.dwList[handle].nextentry =
pDeviceHandle->SurfaceHandleList.dwFreeList;
pDeviceHandle->SurfaceHandleList.dwFreeList = handle;
}
DWORD GetDX7SurfaceHandle (HANDLE hDD)
{
PDDDEVICEHANDLE pDeviceHandle = (PDDDEVICEHANDLE) hDD;
DWORD handle = pDeviceHandle->SurfaceHandleList.dwFreeList;
if (0==handle)
{
// need to grow the dwList
LPDDSURFACELISTENTRY newList;
DWORD newsize;
DWORD index;
if (NULL != pDeviceHandle->SurfaceHandleList.dwList)
{
// old size(current dwFreeList) must not be zero
DDASSERT(0 != pDeviceHandle->SurfaceHandleList.dwList[0].nextentry);
// new dwFreeList is always gonna be the old dwList[0].nextentry
newsize = pDeviceHandle->SurfaceHandleList.dwList[0].nextentry + LISTGROWSIZE;
newList=(LPDDSURFACELISTENTRY)MemAlloc(newsize*sizeof(DDSURFACELISTENTRY));
if (NULL == newList)
{
DPF_ERR("MemAlloc failure in GetSurfaceHandle()");
return 0;
}
pDeviceHandle->SurfaceHandleList.dwFreeList =
pDeviceHandle->SurfaceHandleList.dwList[0].nextentry;
memcpy((LPVOID)newList,(LPVOID)pDeviceHandle->SurfaceHandleList.dwList,
pDeviceHandle->SurfaceHandleList.dwList[0].nextentry*sizeof(DDSURFACELISTENTRY));
MemFree(pDeviceHandle->SurfaceHandleList.dwList);
}
else
{
newsize = LISTGROWSIZE;
newList=(LPDDSURFACELISTENTRY)MemAlloc(newsize*sizeof(DDSURFACELISTENTRY));
if (NULL == newList)
{
DPF_ERR("MemAlloc failure in GetSurfaceHandle()");
return 0;
}
// start from one as we don't want 0 as a valid handle
pDeviceHandle->SurfaceHandleList.dwFreeList = 1;
}
pDeviceHandle->SurfaceHandleList.dwList=newList;
pDeviceHandle->SurfaceHandleList.dwList[0].nextentry=newsize;
for (index = pDeviceHandle->SurfaceHandleList.dwFreeList;
index < newsize - 1;
index++)
{
newList[index].nextentry=index+1;
}
// indicate end of new FreeList
newList[newsize-1].nextentry=0;
// now pop up one and assign it to handle
handle=pDeviceHandle->SurfaceHandleList.dwFreeList;
}
// handle slot is avialable so just remove it from freeList
pDeviceHandle->SurfaceHandleList.dwFreeList =
pDeviceHandle->SurfaceHandleList.dwList[handle].nextentry;
#if DBG
pDeviceHandle->SurfaceHandleList.dwList[handle].nextentry=0xDEADBEEF;
#endif
pDeviceHandle->SurfaceHandleList.dwList[handle].dwFlags=0; //mark it's new
pDeviceHandle->SurfaceHandleList.dwList[handle].lpSurface=NULL;
DDASSERT (handle > 0);
DDASSERT (handle < pDeviceHandle->SurfaceHandleList.dwList[0].nextentry);
return handle;
}
void FreeSurfaceObject (PDDSURFACE pSurf, BOOL bDestroy)
{
if ((pSurf != NULL) &&
!(pSurf->dwFlags & DDSURFACE_DUMMY))
{
if (IS_SOFTWARE_DRIVER_SURFACE(pSurf))
{
LPDDRAWI_DDRAWSURFACE_INT pHeavy;
if (pSurf->Surface.pLight != NULL)
{
pHeavy = GetHeavyweightSurf(pSurf);
if (pHeavy != NULL)
{
if (pSurf->dwFlags & DDSURFACE_CREATECOMPLETE)
{
SwDDIDestroySurface (pSurf->pDevice, pSurf, pHeavy->lpLcl);
}
else if (pSurf->dwFlags & DDSURFACE_CREATEEX)
{
pHeavy->lpLcl->lpGbl->fpVidMem = 0;
SwDDICreateSurfaceEx (pSurf->pDevice->pSwDD->lpLcl,
pHeavy->lpLcl);
}
// Uncache the lightweight surface
if (pSurf->dwFlags & DDSURFACE_LIGHTWEIGHT)
{
pHeavy->dwReserved1 = (ULONG_PTR) NULL;
pHeavy->dwReserved2 = 0;
}
}
MemFree (pSurf->Surface.pLight);
pSurf->Surface.pLight = NULL;
}
if (pSurf->dwCookie != 0)
{
ReleaseDX7SurfaceHandle(pSurf->pDevice, pSurf->dwCookie);
pSurf->dwCookie = 0;
}
}
else if (pSurf->dwFlags & DDSURFACE_HEAVYWEIGHT)
{
// If we created a texture handle, free it now
if ((pSurf->dwFlags & DDSURFACE_DX6HANDLE) &&
(pSurf->pDevice->pContext != NULL) &&
(pSurf->pDevice->pDD->lpLcl->lpGbl->lpD3DHALCallbacks->TextureDestroy != NULL))
{
D3DHAL_TEXTUREDESTROYDATA data;
DWORD ret;
data.dwhContext = (ULONG_PTR) pSurf->pDevice->pContext->Context;
data.dwHandle = pSurf->dwCookie;
CALL_D3DHAL_TAKEBUSY_TAKEWIN16(ret,
pSurf->pDevice,
pSurf->pDevice->pDD->lpLcl->lpGbl->lpD3DHALCallbacks->TextureDestroy,
&data);
}
pSurf->dwFlags &= ~DDSURFACE_DX6HANDLE;
// Now delete the heavy weight surface
if (bDestroy)
{
if (pSurf->Surface.pHeavy != NULL)
{
if (pSurf->dwFlags & DDSURFACE_ROOT)
{
InternalSurfaceRelease(pSurf->Surface.pHeavy, FALSE, TRUE);
}
}
pSurf->Surface.pHeavy = NULL;
}
else if (pSurf->Surface.pHeavy != NULL)
{
invalidateSurface(pSurf->Surface.pHeavy->lpLcl);
}
}
else if (pSurf->Surface.pLight != NULL)
{
LPDDRAWI_DDRAWSURFACE_INT pHeavy;
pHeavy = MapLightweightSurface(pSurf);
if (pHeavy != NULL)
{
if (bDestroy)
{
pHeavy->dwIntRefCnt = 1;
pHeavy->lpLcl->dwLocalRefCnt = 1;
pHeavy->lpLcl->lpGbl->dwRefCnt = 1;
if (pSurf->dwFlags & DDSURFACE_ROOT)
{
pHeavy->lpLcl->lpSurfMore->pAddrefedThisOwner = (IUnknown*) pSurf->pDevice->pDD;
}
pHeavy->lpLcl->dwFlags &= ~DDRAWISURF_IMPLICITCREATE;
InternalSurfaceRelease(pHeavy, TRUE, TRUE);
pHeavy->dwReserved1 = (ULONG_PTR) NULL;
pHeavy->dwReserved2 = 0;
}
else
{
invalidateSurface(pHeavy->lpLcl);
DONE_HEAVYWEIGHT_SURF(pSurf);
}
}
if (bDestroy)
{
MemFree (pSurf->Surface.pLight);
pSurf->Surface.pLight = NULL;
}
}
}
}
/*****************************Private*Routine******************************\
* DdConvertToOldFormat
*
* History:
* 3-Nov-1999 -by- Scott MacDonald [smac]
* Wrote it.
\**************************************************************************/
void ConvertToOldFormat(LPDDPIXELFORMAT pOldFormat, D3DFORMAT NewFormat)
{
// Zero out the format to avoid missing
// cases where it isn't initialized right
ZeroMemory(pOldFormat, sizeof(*pOldFormat));
// Set Size
pOldFormat->dwSize = sizeof(DDPIXELFORMAT);
// Convert away
if (HIWORD((DWORD)NewFormat))
{
pOldFormat->dwFlags = DDPF_FOURCC;
pOldFormat->dwFourCC = (DWORD)NewFormat;
return;
}
switch (NewFormat)
{
case D3DFMT_R8G8B8:
pOldFormat->dwFlags = DDPF_RGB;
pOldFormat->dwRBitMask = 0x00ff0000;
pOldFormat->dwGBitMask = 0x0000ff00;
pOldFormat->dwBBitMask = 0x000000ff;
pOldFormat->dwRGBBitCount = 24;
break;
case D3DFMT_A8R8G8B8:
pOldFormat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
pOldFormat->dwRGBAlphaBitMask = 0xFF000000;
pOldFormat->dwRBitMask = 0x00ff0000;
pOldFormat->dwGBitMask = 0x0000ff00;
pOldFormat->dwBBitMask = 0x000000ff;
pOldFormat->dwRGBBitCount = 32;
break;
case D3DFMT_X8R8G8B8:
pOldFormat->dwFlags = DDPF_RGB;
pOldFormat->dwRBitMask = 0x00ff0000;
pOldFormat->dwGBitMask = 0x0000ff00;
pOldFormat->dwBBitMask = 0x000000ff;
pOldFormat->dwRGBBitCount = 32;
break;
case D3DFMT_R5G6B5:
pOldFormat->dwFlags = DDPF_RGB;
pOldFormat->dwRBitMask = 0x0000f800;
pOldFormat->dwGBitMask = 0x000007e0;
pOldFormat->dwBBitMask = 0x0000001f;
pOldFormat->dwRGBBitCount = 16;
break;
case D3DFMT_X1R5G5B5:
pOldFormat->dwFlags = DDPF_RGB;
pOldFormat->dwRBitMask = 0x00007c00;
pOldFormat->dwGBitMask = 0x000003e0;
pOldFormat->dwBBitMask = 0x0000001f;
pOldFormat->dwRGBBitCount = 16;
break;
case D3DFMT_A1R5G5B5:
pOldFormat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
pOldFormat->dwRGBAlphaBitMask = 0x00008000;
pOldFormat->dwRBitMask = 0x00007c00;
pOldFormat->dwGBitMask = 0x000003e0;
pOldFormat->dwBBitMask = 0x0000001f;
pOldFormat->dwRGBBitCount = 16;
break;
case D3DFMT_A4R4G4B4:
pOldFormat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
pOldFormat->dwRGBAlphaBitMask = 0x0000f000;
pOldFormat->dwRBitMask = 0x00000f00;
pOldFormat->dwGBitMask = 0x000000f0;
pOldFormat->dwBBitMask = 0x0000000f;
pOldFormat->dwRGBBitCount = 16;
break;
case D3DFMT_X4R4G4B4:
pOldFormat->dwFlags = DDPF_RGB;
pOldFormat->dwRBitMask = 0x00000f00;
pOldFormat->dwGBitMask = 0x000000f0;
pOldFormat->dwBBitMask = 0x0000000f;
pOldFormat->dwRGBBitCount = 16;
break;
case D3DFMT_R3G3B2:
pOldFormat->dwFlags = DDPF_RGB;
pOldFormat->dwRBitMask = 0x000000e0;
pOldFormat->dwGBitMask = 0x0000001c;
pOldFormat->dwBBitMask = 0x00000003;
pOldFormat->dwRGBBitCount = 8;
break;
case D3DFMT_A8R3G3B2:
pOldFormat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
pOldFormat->dwRGBAlphaBitMask = 0x0000FF00;
pOldFormat->dwRBitMask = 0x000000e0;
pOldFormat->dwGBitMask = 0x0000001c;
pOldFormat->dwBBitMask = 0x00000003;
pOldFormat->dwRGBBitCount = 16;
break;
case D3DFMT_A8P8:
pOldFormat->dwFlags = DDPF_RGB |
DDPF_ALPHAPIXELS |
DDPF_PALETTEINDEXED8;
pOldFormat->dwRGBAlphaBitMask = 0x0000FF00;
pOldFormat->dwRGBBitCount = 16;
break;
case D3DFMT_P8:
pOldFormat->dwFlags = DDPF_RGB |
DDPF_PALETTEINDEXED8;
pOldFormat->dwRGBBitCount = 8;
break;
case D3DFMT_L8:
pOldFormat->dwFlags = DDPF_LUMINANCE;
pOldFormat->dwLuminanceBitMask = 0x000000FF;
pOldFormat->dwLuminanceBitCount = 8;
break;
case D3DFMT_A8L8:
pOldFormat->dwFlags = DDPF_LUMINANCE |
DDPF_ALPHAPIXELS;
pOldFormat->dwLuminanceAlphaBitMask = 0x0000FF00;
pOldFormat->dwLuminanceBitMask = 0x000000FF;
pOldFormat->dwLuminanceBitCount = 16;
break;
case D3DFMT_A4L4:
pOldFormat->dwFlags = DDPF_LUMINANCE |
DDPF_ALPHAPIXELS;
pOldFormat->dwLuminanceAlphaBitMask = 0x000000F0;
pOldFormat->dwLuminanceBitMask = 0x0000000F;
pOldFormat->dwLuminanceBitCount = 8;
break;
case D3DFMT_V8U8:
pOldFormat->dwFlags = DDPF_BUMPDUDV;
pOldFormat->dwBumpDvBitMask = 0x0000FF00;
pOldFormat->dwBumpDuBitMask = 0x000000FF;
pOldFormat->dwBumpBitCount = 16;
break;
case D3DFMT_L6V5U5:
pOldFormat->dwFlags = DDPF_BUMPDUDV |
DDPF_BUMPLUMINANCE;
pOldFormat->dwBumpLuminanceBitMask = 0x0000FC00;
pOldFormat->dwBumpDvBitMask = 0x000003E0;
pOldFormat->dwBumpDuBitMask = 0x0000001F;
pOldFormat->dwBumpBitCount = 16;
break;
case D3DFMT_X8L8V8U8:
pOldFormat->dwFlags = DDPF_BUMPDUDV |
DDPF_BUMPLUMINANCE;
pOldFormat->dwBumpLuminanceBitMask = 0x00FF0000;
pOldFormat->dwBumpDvBitMask = 0x0000FF00;
pOldFormat->dwBumpDuBitMask = 0x000000FF;
pOldFormat->dwBumpBitCount = 32;
break;
case D3DFMT_A8:
pOldFormat->dwFlags = DDPF_ALPHA;
pOldFormat->dwAlphaBitDepth = 8;
break;
case D3DFMT_D16:
case D3DFMT_D16_LOCKABLE:
pOldFormat->dwFlags = DDPF_ZBUFFER;
pOldFormat->dwZBufferBitDepth = 16;
pOldFormat->dwZBitMask = 0xFFFF;
pOldFormat->dwStencilBitDepth = 0;
pOldFormat->dwStencilBitMask = 0;
break;
case D3DFMT_D32:
pOldFormat->dwFlags = DDPF_ZBUFFER;
pOldFormat->dwZBufferBitDepth = 32;
pOldFormat->dwZBitMask = 0xFFFFFFFF;
pOldFormat->dwStencilBitDepth = 0;
pOldFormat->dwStencilBitMask = 0;
break;
case D3DFMT_D15S1:
pOldFormat->dwFlags = DDPF_ZBUFFER |
DDPF_STENCILBUFFER;
pOldFormat->dwZBufferBitDepth = 16;
pOldFormat->dwZBitMask = 0xFFFE;
pOldFormat->dwStencilBitDepth = 1;
pOldFormat->dwStencilBitMask = 0x0001;
break;
case D3DFMT_D24S8:
pOldFormat->dwFlags = DDPF_ZBUFFER |
DDPF_STENCILBUFFER;
pOldFormat->dwZBufferBitDepth = 32;
pOldFormat->dwZBitMask = 0xFFFFFF00;
pOldFormat->dwStencilBitDepth = 8;
pOldFormat->dwStencilBitMask = 0xFF;
break;
case D3DFMT_S1D15:
pOldFormat->dwFlags = DDPF_ZBUFFER |
DDPF_STENCILBUFFER;;
pOldFormat->dwZBufferBitDepth = 16;
pOldFormat->dwZBitMask = 0x7FFF;
pOldFormat->dwStencilBitDepth = 1;
pOldFormat->dwStencilBitMask = 0x8000;
break;
case D3DFMT_S8D24:
pOldFormat->dwFlags = DDPF_ZBUFFER |
DDPF_STENCILBUFFER;;
pOldFormat->dwZBufferBitDepth = 32;
pOldFormat->dwZBitMask = 0x00FFFFFF;
pOldFormat->dwStencilBitDepth = 8;
pOldFormat->dwStencilBitMask = 0xFF000000;
break;
case D3DFMT_X8D24:
pOldFormat->dwFlags = DDPF_ZBUFFER;
pOldFormat->dwZBufferBitDepth = 32;
pOldFormat->dwZBitMask = 0x00FFFFFF;
pOldFormat->dwStencilBitDepth = 0;
pOldFormat->dwStencilBitMask = 0x00000000;
break;
case D3DFMT_D24X8:
pOldFormat->dwFlags = DDPF_ZBUFFER;
pOldFormat->dwZBufferBitDepth = 32;
pOldFormat->dwZBitMask = 0xFFFFFF00;
pOldFormat->dwStencilBitDepth = 0;
pOldFormat->dwStencilBitMask = 0x00000000;
break;
case D3DFMT_D24X4S4:
pOldFormat->dwFlags = DDPF_ZBUFFER |
DDPF_STENCILBUFFER;
pOldFormat->dwZBufferBitDepth = 32;
pOldFormat->dwZBitMask = 0xFFFFFF00;
pOldFormat->dwStencilBitDepth = 4;
pOldFormat->dwStencilBitMask = 0x0000000F;
break;
case D3DFMT_X4S4D24:
pOldFormat->dwFlags = DDPF_ZBUFFER |
DDPF_STENCILBUFFER;
pOldFormat->dwZBufferBitDepth = 32;
pOldFormat->dwZBitMask = 0x00FFFFFF;
pOldFormat->dwStencilBitDepth = 4;
pOldFormat->dwStencilBitMask = 0x0F000000;
break;
default:
// All other formats are treated as a
// FOURCC
pOldFormat->dwFlags = DDPF_FOURCC;
pOldFormat->dwFourCC = (DWORD)NewFormat;
break;
}
return;
}
/*****************************Private*Routine******************************\
* DdConvertFromOldFormat
*
* History:
* 13-Nov-1999 -by- Scott MacDonald [smac]
* Wrote it.
\**************************************************************************/
void ConvertFromOldFormat(LPDDPIXELFORMAT pOldFormat, D3DFORMAT *pNewFormat)
{
*pNewFormat = D3DFMT_UNKNOWN;
if (pOldFormat->dwFlags & DDPF_FOURCC)
{
((DWORD)*pNewFormat) = 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;
}
}
else if (pOldFormat->dwFlags == DDPF_ALPHA)
{
if (pOldFormat->dwAlphaBitDepth == 8)
{
*pNewFormat = D3DFMT_A8;
}
}
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;
}
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;
}
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;
}
}
}
// How lost devices work:
//
// Device can be lost two ways:
// 1) A mode change or something occurs, in which DDraw knows about it and
// calls CleanupD3D8. In this case, we free the surfaces and mark the
// device as lost.
//
// This will only happen when the DDRAW critical section is held, so as long
// as we check for lost devices while the critical section is held, we are
// safe to use the surface structures.
//
// 2) A DOS box or something occurs in which case we don't know about it,
// but we can find out by polling the busy bit. This can occur at anytime,
// although we are gaurenteed that it will never happen while we are holding
// the win16 lock. In fact, if we don't hold the win16 lock while checking
// the busy bit, we will get false positives simple by dragging another window
// around.
//
// So, we have to grab the busy bit to check for lost, and we need to hold the
// DDraw critical section throughout the remained of the call since not holding
// it can cause surfaces to go away out from under us. Also, when calling HAL
// we always grab the win16 lock, so in each call we could be grabbing it twice.
// With all of this in mind, it's probably better just to ENTER_BOTH() before
// we check for device lost and then LEAVE_BOTH() at the end of the funtion.
//
// We can also remove the busybit check from the HAL call since we already know
// that it's not set since we checked it and are still holding the win16 lock, so
// nobody else can set.
void LoseDevice (DDDEVICEHANDLE* pDevice)
{
DDSURFACE* pSurf;
if (!pDevice->bDeviceLost)
{
// The device has transitioned to the lost state, so we need
// walk through the list and free the vidmem surfaces..
pDevice->bDeviceLost = TRUE;
pSurf = pDevice->pSurfList;
while (pSurf != NULL)
{
if (IS_SURFACE_LOOSABLE(pSurf))
{
FreeSurfaceObject(pSurf, FALSE);
}
pSurf = pSurf->pNext;
}
}
}
BOOL CheckForDeviceLost (HANDLE hDD)
{
PDDDEVICEHANDLE pDeviceHandle = (PDDDEVICEHANDLE) hDD;
PDDSURFACE pSurf;
if (pDeviceHandle->bDeviceLost)
{
return TRUE;
}
// The below check will only be reliable if we are holding the win16 lock.
// if dwWin16LockCnt != 0 that means BUSY bit was set by DdLock
if ( 0 == pDeviceHandle->pDD->lpLcl->lpGbl->dwWin16LockCnt &&
(*(pDeviceHandle->pDD->lpLcl->lpGbl->lpwPDeviceFlags) & BUSY )
)
{
LoseDevice(pDeviceHandle);
return TRUE;
}
return FALSE;
}
DWORD WINAPI DdBlt( PD3D8_BLTDATA pBlt )
{
DDSURFACE* pSrcSurf = (DDSURFACE*) pBlt->hSrcSurface;
DDSURFACE* pDstSurf = (DDSURFACE*) pBlt->hDestSurface;
PDDDEVICEHANDLE pDevice = (PDDDEVICEHANDLE) pBlt->hDD;
// Return failure on bad paths
pBlt->ddRVal = E_FAIL;
ENTER_BOTH();
if (CheckForDeviceLost(pBlt->hDD))
{
// Some blts should fail, others should succeed:
// persistant -> non persitant : OK
// persistant -> persitant : FAIL
// non persistant -> persistant : FAIL
// non persistant -> non persistant : OK
if ((pDstSurf->Pool == D3DPOOL_LOCALVIDMEM) ||
(pDstSurf->Pool == D3DPOOL_NONLOCALVIDMEM))
{
pBlt->ddRVal = DD_OK;
}
else
{
pBlt->ddRVal = D3DERR_DEVICELOST;
}
LEAVE_BOTH();
return DDHAL_DRIVER_HANDLED;
}
#ifdef DEBUG
// Just a colorfill? Used only in debug for
// enforcing DISCARD
if (pSrcSurf == NULL)
{
LPDDRAWI_DDRAWSURFACE_INT pHeavyDst;
pHeavyDst = GetHeavyweightSurf(pDstSurf);
if (pHeavyDst != NULL)
{
pBlt->bltFX.dwSize = sizeof(DDBLTFX);
pBlt->ddRVal = DD_Surface_Blt((LPDIRECTDRAWSURFACE)pHeavyDst,
NULL,
NULL,
NULL,
pBlt->dwFlags,
&pBlt->bltFX);
if (FAILED(pBlt->ddRVal))
{
DPF_ERR("Driver failed color-fill blt");
}
DONE_HEAVYWEIGHT_SURF(pDstSurf);
}
pBlt->ddRVal = S_OK;
LEAVE_BOTH();
return S_OK;
}
#endif
if (DDBLT_COPYVSYNC & pBlt->dwFlags)
{
DWORD msCurrentTime;
DWORD threshold;
// Compute how many milliseconds there
// are per refresh. We round down.
if (pDevice->pDD->lpLcl->lpGbl->dwMonitorFrequency == 0)
{
// 60Hz = 16.666ms per frame
// 75Hz = 13.333ms
// 85Hz = 11.765ms
threshold = 13;
}
else
{
threshold = (DWORD)(1000.0f /
(float)(pDevice->pDD->lpLcl->lpGbl->dwMonitorFrequency));
}
while (1)
{
msCurrentTime = GetTickCount();
// If the previous blt was long
// enough ago i.e. a refresh, then
// we can break out this loop
if ((msCurrentTime - pBlt->msLastPresent) > threshold )
break;
}
// For DDBLT_COPYVSYNC remember the
// time for this blt was sent
pBlt->msLastPresent = msCurrentTime;
}
if ((pSrcSurf) && (pDstSurf))
{
if ((pSrcSurf->Format == pDstSurf->Format ||
(pBlt->dwFlags & DDBLT_WINDOWCLIP)) &&
!IS_SOFTWARE_DRIVER_SURFACE(pSrcSurf) &&
!IS_SOFTWARE_DRIVER_SURFACE(pDstSurf))
{
LPDDRAWI_DDRAWSURFACE_INT pHeavySrc;
LPDDRAWI_DDRAWSURFACE_INT pHeavyDst;
DWORD dwFlags = pBlt->dwFlags & ~DDBLT_WINDOWCLIP;
pHeavySrc = GetHeavyweightSurf(pSrcSurf);
if (pHeavySrc == NULL)
{
pBlt->ddRVal = DDERR_OUTOFMEMORY;
LEAVE_BOTH();
return DDHAL_DRIVER_HANDLED;
}
pHeavyDst = GetHeavyweightSurf(pDstSurf);
if (pHeavyDst == NULL)
{
DONE_HEAVYWEIGHT_SURF(pSrcSurf);
pBlt->ddRVal = DDERR_OUTOFMEMORY;
LEAVE_BOTH();
return DDHAL_DRIVER_HANDLED;
}
if ((pBlt->hWnd) && (DDBLT_WINDOWCLIP & pBlt->dwFlags))
{
LPDDRAWI_DDRAWCLIPPER_INT pcClipper = pHeavyDst->lpLcl->lpSurfMore->lpDDIClipper;
DDASSERT(IsWindow(pBlt->hWnd));
DDASSERT(DDSCAPS_PRIMARYSURFACE & pHeavyDst->lpLcl->ddsCaps.dwCaps);
DDASSERT(pcClipper);
if (pcClipper)
{
(HWND) pcClipper->lpLcl->lpGbl->hWnd = pBlt->hWnd;
dwFlags |= DDBLT_WINDOWCLIP;
DPF(10,"Updated hWnd=%08lx", pBlt->hWnd);
}
}
pBlt->bltFX.dwSize = sizeof(DDBLTFX);
pBlt->bltFX.dwROP = SRCCOPY;
pBlt->ddRVal = DD_Surface_Blt((LPDIRECTDRAWSURFACE)pHeavyDst,
(LPRECT) &(pBlt->rDest),
(LPDIRECTDRAWSURFACE)pHeavySrc,
(LPRECT) &(pBlt->rSrc),
dwFlags,
&pBlt->bltFX);
DONE_HEAVYWEIGHT_SURF(pSrcSurf);
DONE_HEAVYWEIGHT_SURF(pDstSurf);
}
if (FAILED(pBlt->ddRVal))
{
// !!! Just use GetDC on the DirectDraw surface for now, though this is
// probably way too slow on drivers which do not support derived
// surfaces. DirectDraw Blt support should be added soon.
HDC hDCTarget;
if ((pBlt->hWnd) && (DDBLT_WINDOWCLIP & pBlt->dwFlags))
hDCTarget = GetDC(pBlt->hWnd);
else
hDCTarget = D3D8GetDC(pBlt->hDestSurface, NULL);
if (hDCTarget != NULL)
{
HDC hDCSource = D3D8GetDC(pBlt->hSrcSurface, NULL);
if (hDCSource != NULL)
{
LONG DestWidth=pBlt->rDest.right - pBlt->rDest.left;
LONG DestHeight= pBlt->rDest.bottom - pBlt->rDest.top;
LONG SrcWidth= pBlt->rSrc.right - pBlt->rSrc.left;
LONG SrcHeight= pBlt->rSrc.bottom - pBlt->rSrc.top;
if (DestWidth == SrcWidth && DestHeight == SrcHeight)
{
if (BitBlt(
hDCTarget,
pBlt->rDest.left,
pBlt->rDest.top,
DestWidth,
DestHeight,
hDCSource,
pBlt->rSrc.left,
pBlt->rSrc.top,
SRCCOPY))
{
pBlt->ddRVal = S_OK;
}
}
else
{
// COLORONCOLOR is not the default in NT
int saved = SetStretchBltMode(hDCTarget,COLORONCOLOR);
if (StretchBlt(
hDCTarget,
pBlt->rDest.left,
pBlt->rDest.top,
DestWidth,
DestHeight,
hDCSource,
pBlt->rSrc.left,
pBlt->rSrc.top,
SrcWidth,
SrcHeight,
SRCCOPY))
{
pBlt->ddRVal = S_OK;
}
// restore to previous mode
if (saved)
SetStretchBltMode(hDCTarget,saved);
}
D3D8ReleaseDC(pBlt->hSrcSurface, hDCSource);
}
if ((pBlt->hWnd) && (DDBLT_WINDOWCLIP & pBlt->dwFlags))
ReleaseDC(pBlt->hWnd, hDCTarget);
else
D3D8ReleaseDC(pBlt->hDestSurface, hDCTarget);
}
}
// We only want to report DP2 errors during the present call because
// checking for it everywhere is too hard.
if ((pBlt->ddRVal == DD_OK) &&
(pDevice->bDP2Error) &&
(pBlt->dwFlags & DDBLT_WINDOWCLIP))
{
pDevice->bDP2Error = FALSE;
// We use a special error here to mean that the blt succeeded
// but that that some DP2 failed since the last present
pBlt->ddRVal = D3DERR_DEFERRED_DP2ERROR;
}
LEAVE_BOTH();
pBlt->ddRVal = MapLegacyResult(pBlt->ddRVal);
return DDHAL_DRIVER_HANDLED;
}
LEAVE_BOTH();
pBlt->ddRVal = MapLegacyResult(pBlt->ddRVal);
return DDHAL_DRIVER_NOTHANDLED;
}
DWORD APIENTRY DdFlip( PD3D8_FLIPDATA pFlip )
{
DDSURFACE* pCurrSurf = (DDSURFACE*) pFlip->hSurfCurr;
DDSURFACE* pTargSurf = (DDSURFACE*) pFlip->hSurfTarg;
ENTER_BOTH();
if (CheckForDeviceLost(pFlip->hDD))
{
LEAVE_BOTH();
pFlip->ddRVal = DD_OK;
return DDHAL_DRIVER_HANDLED;
}
if ((pCurrSurf) && (pCurrSurf->dwFlags & DDSURFACE_HEAVYWEIGHT) &&
(pTargSurf) && (pTargSurf->dwFlags & DDSURFACE_HEAVYWEIGHT))
{
pFlip->ddRVal = MapLegacyResult( DD_Surface_Flip((LPDIRECTDRAWSURFACE)pCurrSurf->Surface.pHeavy,
(LPDIRECTDRAWSURFACE)pTargSurf->Surface.pHeavy,
pFlip->dwFlags));
if (SUCCEEDED(pFlip->ddRVal))
{
DDSURFACE Temp;
// The DirectX runtime swaps the surface handles when it flips, so we
// need to swap them back to preserve the integrity
Temp = *pCurrSurf;
DDASSERT(pCurrSurf->Pitch == pTargSurf->Pitch);
DDASSERT(pCurrSurf->Pool == pTargSurf->Pool);
DDASSERT(pCurrSurf->Type == pTargSurf->Type);
DDASSERT(pCurrSurf->Height == pTargSurf->Height);
pCurrSurf->dwFlags = pTargSurf->dwFlags;
pCurrSurf->Surface = pTargSurf->Surface;
pCurrSurf->fpVidMem = pTargSurf->fpVidMem;
pCurrSurf->pBits = pTargSurf->pBits;
pCurrSurf->LockFlags = pTargSurf->LockFlags;
pCurrSurf->LockRect = pTargSurf->LockRect;
pTargSurf->dwFlags = Temp.dwFlags;
pTargSurf->Surface = Temp.Surface;
pTargSurf->fpVidMem = Temp.fpVidMem;
pTargSurf->pBits = Temp.pBits;
pTargSurf->LockFlags = Temp.LockFlags;
pTargSurf->LockRect = Temp.LockRect;
// We only want to report DP2 errors during the present call because
// checking for it everywhere is too hard.
if (((DDDEVICEHANDLE*)pFlip->hDD)->bDP2Error)
{
((DDDEVICEHANDLE*)pFlip->hDD)->bDP2Error = FALSE;
// We use a special error here to mean that the flip succeeded
// but that that some DP2 failed since the last present
pFlip->ddRVal = D3DERR_DEFERRED_DP2ERROR;
}
}
LEAVE_BOTH();
return DDHAL_DRIVER_HANDLED;
}
LEAVE_BOTH();
return DDHAL_DRIVER_NOTHANDLED;
}
DWORD APIENTRY DdLock( PD3D8_LOCKDATA pLock )
{
PDDSURFACE pSurf = (PDDSURFACE) pLock->hSurface;
HRESULT hr;
LPDDRAWI_DDRAWSURFACE_INT pHeavyInt;
// Mask off new flags
pLock->dwFlags &= (D3DLOCK_READONLY |
D3DLOCK_DISCARD |
D3DLOCK_NOOVERWRITE |
D3DLOCK_NOSYSLOCK);
// Always turn on Wait
pLock->dwFlags |= DDLOCK_WAIT;
if (pSurf->Pool == D3DPOOL_SYSTEMMEM)
{
DWORD Width;
if (pSurf->dwFlags & DDSURFACE_LIGHTWEIGHT)
{
pLock->lpSurfData = (LPVOID) pSurf->Surface.pLight->fpGblVidMem;
pLock->lPitch = pSurf->Surface.pLight->GblPitch;
Width = pSurf->Surface.pLight->GblWidth;
}
else
{
ENTER_DDRAW();
pLock->lpSurfData = (LPVOID) pSurf->Surface.pHeavy->lpLcl->lpGbl->fpVidMem;
pLock->lPitch = pSurf->Surface.pHeavy->lpLcl->lpGbl->lPitch;
Width = (DWORD) pSurf->Surface.pHeavy->lpLcl->lpGbl->wWidth;
LEAVE_DDRAW();
}
if (pLock->bHasRange)
{
((BYTE*)pLock->lpSurfData) += pLock->lPitch * pLock->range.Offset;
}
else if (pLock->bHasRect)
{
((BYTE*)pLock->lpSurfData) += pLock->lPitch * pLock->rArea.top;
((BYTE*)pLock->lpSurfData) += (pLock->lPitch / Width) * pLock->rArea.left;
}
hr = DD_OK;
}
else if (IS_SOFTWARE_DRIVER_SURFACE(pSurf))
{
ENTER_DDRAW();
pHeavyInt = GetHeavyweightSurf(pSurf);
if (pHeavyInt == NULL)
{
// This can be caused by an out of memory condition when calling
// MapLightweightSurface
hr = DDERR_OUTOFMEMORY;
}
else
{
if(pLock->bHasRange)
{
pLock->bHasRange = FALSE;
pLock->bHasRect = TRUE;
pLock->rArea.left = 0;
pLock->rArea.right = 0;
pLock->rArea.top = pLock->range.Offset;
pLock->rArea.bottom = pLock->range.Offset + pLock->range.Size;
}
hr = SwDDILock (pLock->hDD, pSurf, pLock, pHeavyInt->lpLcl);
pLock->lPitch = pHeavyInt->lpLcl->lpGbl->lPitch;
}
LEAVE_DDRAW();
}
else
{
ENTER_BOTH();
if ((CheckForDeviceLost(pLock->hDD) &&
pSurf->Pool != D3DPOOL_MANAGED) ||
(pSurf->dwFlags & DDSURFACE_SYSMEMALLOCATED))
{
DWORD Height = pSurf->Height;
if (Height == 0)
{
Height++;
}
if ((pSurf->fpVidMem == NULL) ||
!(pSurf->dwFlags & DDSURFACE_SYSMEMALLOCATED))
{
DDASSERT(pSurf->Pool != D3DPOOL_MANAGED);
if ((pSurf->Type == D3DRTYPE_VOLUME) ||
(pSurf->Type == D3DRTYPE_VOLUMETEXTURE))
{
// For volumes, height actually contains the depth
pSurf->fpVidMem = (char*) MemAlloc(
pSurf->iSlicePitch * Height);
}
else
{
pSurf->fpVidMem = (char*)MemAlloc(pSurf->Pitch * Height);
}
if (pSurf->fpVidMem != NULL)
{
pSurf->dwFlags |= DDSURFACE_SYSMEMALLOCATED;
}
}
if (pSurf->dwFlags & DDSURFACE_SYSMEMALLOCATED)
{
DDASSERT(CheckForDeviceLost(pLock->hDD));
pLock->lPitch = pSurf->Pitch;
pLock->lpSurfData = pSurf->fpVidMem;
pSurf->dwFlags |= DDSURFACE_SYSMEMLOCK;
if ((pSurf->Type == D3DRTYPE_VOLUME) ||
(pSurf->Type == D3DRTYPE_VOLUMETEXTURE))
{
pLock->lSlicePitch = pSurf->iSlicePitch;
}
hr = DD_OK;
}
else
{
hr = DDERR_GENERIC;
}
}
else
{
pHeavyInt = GetHeavyweightSurf(pSurf);
if (pHeavyInt == NULL)
{
// This can be caused by an out of memory condition when calling
// MapLightweightSurface
hr = DDERR_OUTOFMEMORY;
}
else
{
if(pLock->bHasRange)
{
pLock->bHasRect = TRUE;
pSurf->LockRect.left = 0;
pSurf->LockRect.right = 0;
pSurf->LockRect.top = pLock->range.Offset;
pSurf->LockRect.bottom = pLock->range.Offset + pLock->range.Size;
}
else
{
pSurf->LockRect.left = pLock->rArea.left;
pSurf->LockRect.right = pLock->rArea.right;
pSurf->LockRect.top = pLock->rArea.top;
pSurf->LockRect.bottom = pLock->rArea.bottom;
}
if (pLock->bHasBox)
{
pLock->bHasRect = TRUE;
pSurf->LockRect.left = pLock->box.Left;
pSurf->LockRect.right = pLock->box.Right;
pSurf->LockRect.top = pLock->box.Top;
pSurf->LockRect.bottom = pLock->box.Bottom;
pSurf->LockRect.left |= (pLock->box.Front << 16);
pSurf->LockRect.right |= (pLock->box.Back << 16);
}
hr = InternalLock (pHeavyInt->lpLcl,
&pLock->lpSurfData,
pLock->bHasRect ? &pSurf->LockRect : NULL,
pLock->dwFlags | DDLOCK_NOSYSLOCK | (pSurf->Pool == D3DPOOL_MANAGED ? 0 : DDLOCK_TAKE_WIN16));
if (hr == DD_OK)
{
pLock->lPitch = pHeavyInt->lpLcl->lpGbl->lPitch;
pSurf->pBits = pLock->lpSurfData;
pSurf->LockFlags = pLock->dwFlags;
if (pLock->bHasRect)
{
pSurf->dwFlags |= DDSURFACE_LOCKRECT;
}
}
}
}
LEAVE_BOTH();
}
if ((pSurf->Type == D3DRTYPE_VOLUME) ||
(pSurf->Type == D3DRTYPE_VOLUMETEXTURE))
{
pLock->lSlicePitch = pSurf->iSlicePitch;
}
return MapLegacyResult(hr);
}
DWORD APIENTRY DdUnlock( PD3D8_UNLOCKDATA pUnlock )
{
PDDSURFACE pSurf = (PDDSURFACE) pUnlock->hSurface;
HRESULT hr = DDERR_GENERIC;
LPDDRAWI_DDRAWSURFACE_INT pHeavy;
if (pSurf->Pool == D3DPOOL_SYSTEMMEM)
{
hr = DD_OK;
}
else
{
if (IS_SOFTWARE_DRIVER_SURFACE(pSurf))
{
ENTER_DDRAW();
if (pSurf->dwFlags & DDSURFACE_LIGHTWEIGHT)
{
pHeavy = GET_CACHED_LIGHTWEIGHT_INT(pSurf);
DDASSERT(pHeavy != NULL);
}
else
{
pHeavy = pSurf->Surface.pHeavy;
}
hr = SwDDIUnlock (pUnlock->hDD, pSurf, pUnlock, pHeavy->lpLcl);
DONE_HEAVYWEIGHT_SURF(pSurf);
LEAVE_DDRAW();
}
else
{
if (pSurf->dwFlags & DDSURFACE_SYSMEMLOCK)
{
pSurf->dwFlags &= ~DDSURFACE_SYSMEMLOCK;
hr = DD_OK;
}
else if (pSurf->LockFlags)
{
ENTER_BOTH();
if (CheckForDeviceLost(pUnlock->hDD) && pSurf->Pool != D3DPOOL_MANAGED)
{
hr = DD_OK;
}
else
{
if (pSurf->dwFlags & DDSURFACE_LIGHTWEIGHT)
{
pHeavy = GET_CACHED_LIGHTWEIGHT_INT(pSurf);
DDASSERT(pHeavy != NULL);
}
else
{
pHeavy = pSurf->Surface.pHeavy;
}
hr = InternalUnlock (pHeavy->lpLcl,
(pSurf->dwFlags & DDSURFACE_LOCKRECT) ? NULL : pSurf->pBits,
(pSurf->dwFlags & DDSURFACE_LOCKRECT) ? &pSurf->LockRect : NULL,
pSurf->LockFlags | DDLOCK_NOSYSLOCK | (pSurf->Pool == D3DPOOL_MANAGED ? 0 : DDLOCK_TAKE_WIN16));
pSurf->LockFlags = 0;
pSurf->dwFlags &= ~DDSURFACE_LOCKRECT;
DONE_HEAVYWEIGHT_SURF(pSurf);
}
LEAVE_BOTH();
}
}
}
return MapLegacyResult(hr);
}
DWORD APIENTRY DdGetBltStatus( PD3D8_GETBLTSTATUSDATA pGetBltStatus )
{
PDDDEVICEHANDLE pDevice = (PDDDEVICEHANDLE) pGetBltStatus->hDD;
PDDSURFACE pSurf = (PDDSURFACE) pGetBltStatus->hSurface;
DDHAL_GETBLTSTATUSDATA gbsd;
LPDDHALSURFCB_GETBLTSTATUS gbsfn;
// Software drivers will only do memcpy, so we don't need to call
// the driver
pGetBltStatus->ddRVal = DD_OK;
if (IS_SOFTWARE_DRIVER(pDevice))
{
return DDHAL_DRIVER_HANDLED;
}
ENTER_BOTH();
pGetBltStatus->ddRVal = DD_OK;
if (CheckForDeviceLost(pDevice))
{
LEAVE_BOTH();
return DDHAL_DRIVER_HANDLED;
}
/*
gbsfn = pDevice->pDD->lpLcl->lpDDCB->HALDDMiscellaneous.GetSysmemBltStatus;
gbsd.GetBltStatus = pDevice->pDD->lpLcl->lpDDCB->HALDDMiscellaneous.GetSysmemBltStatus;
if( gbsd.GetBltStatus != NULL )
{
DWORD rc;
gbsd.lpDD = pDevice->pDD->lpLcl->lpGbl;
gbsd.dwFlags = pGetBltStatus->dwFlags;
gbsd.lpDDSurface = pSurf->Surface.pHeavy->lpLcl;
DOHALCALL( GetBltStatus, gbsfn, gbsd, rc, FALSE );
if( rc == DDHAL_DRIVER_HANDLED )
{
pGetBltStatus->ddRVal = gbsd.ddRVal;
}
}
*/
LEAVE_BOTH();
return DDHAL_DRIVER_HANDLED;
}
DWORD APIENTRY DdGetFlipStatus( PD3D8_GETFLIPSTATUSDATA pGetFlipStatus )
{
DPF_ERR("DdGetFlipStatus");
return DD_OK;
}
DWORD APIENTRY DdSetMode( PD3D8_SETMODEDATA pSetMode )
{
UINT BPP;
PDDDEVICEHANDLE pDeviceHandle = (PDDDEVICEHANDLE) pSetMode->hDD;
pSetMode->ddRVal = D3DERR_DRIVERINTERNALERROR;
switch (pSetMode->Format)
{
case D3DFMT_P8:
BPP = 8;
break;
case D3DFMT_R5G6B5:
case D3DFMT_X1R5G5B5:
BPP = 16;
break;
case D3DFMT_R8G8B8:
BPP = 24;
break;
case D3DFMT_A8R8G8B8:
case D3DFMT_X8R8G8B8:
BPP = 32;
break;
default:
return DDHAL_DRIVER_HANDLED;
}
pSetMode->ddRVal = D3D8SetMode((HANDLE)pDeviceHandle,
pDeviceHandle->szDeviceName,
pSetMode->dwWidth,
pSetMode->dwHeight,
BPP,
pSetMode->dwRefreshRate,
FALSE);
return DDHAL_DRIVER_HANDLED;
}
DWORD APIENTRY DdDestroyDDLocal( PD3D8_DESTROYDDLOCALDATA pDestroyDDLocal )
{
DPF_ERR("DdDestroyDDLocal");
return DD_OK;
}
DWORD APIENTRY DdWaitForVerticalBlank( PD3D8_WAITFORVERTICALBLANKDATA pWaitForVerticalBlank )
{
PDDDEVICEHANDLE pDevice = (PDDDEVICEHANDLE) pWaitForVerticalBlank->hDD;
LPDDHAL_WAITFORVERTICALBLANK wfvbhalfn;
LPDDHAL_WAITFORVERTICALBLANK wfvbfn;
DWORD dwRet = DDHAL_DRIVER_HANDLED;
ENTER_BOTH();
if (CheckForDeviceLost(pDevice))
{
static int LostTestVerticalBlank;
pWaitForVerticalBlank->ddRVal = DD_OK;
if (pWaitForVerticalBlank->dwFlags == DDWAITVB_I_TESTVB)
{
if (LostTestVerticalBlank > 0)
{
pWaitForVerticalBlank->bIsInVB = TRUE;
}
else
{
pWaitForVerticalBlank->bIsInVB = FALSE;
}
LostTestVerticalBlank = LostTestVerticalBlank == 0 ? 1 : 0;
}
else if (pWaitForVerticalBlank->dwFlags == DDWAITVB_BLOCKEND)
{
pWaitForVerticalBlank->bIsInVB = FALSE;
}
else
{
pWaitForVerticalBlank->bIsInVB = TRUE;
}
}
else
{
wfvbfn = pDevice->pDD->lpLcl->lpDDCB->HALDD.WaitForVerticalBlank;
wfvbhalfn = pDevice->pDD->lpLcl->lpDDCB->cbDDCallbacks.WaitForVerticalBlank;
dwRet = DDHAL_DRIVER_NOTHANDLED;
if( wfvbhalfn != NULL )
{
DDHAL_WAITFORVERTICALBLANKDATA wfvbd;
wfvbd.WaitForVerticalBlank = wfvbhalfn;
wfvbd.lpDD = pDevice->pDD->lpLcl->lpGbl;
wfvbd.dwFlags = pWaitForVerticalBlank->dwFlags;
wfvbd.hEvent = (ULONG_PTR) NULL;
DOHALCALL( WaitForVerticalBlank, wfvbfn, wfvbd, dwRet, FALSE );
if (dwRet == DDHAL_DRIVER_HANDLED)
{
pWaitForVerticalBlank->ddRVal = MapLegacyResult(wfvbd.ddRVal);
if (wfvbd.ddRVal == DDERR_VERTICALBLANKINPROGRESS)
{
pWaitForVerticalBlank->ddRVal = DD_OK;
pWaitForVerticalBlank->bIsInVB = TRUE;
}
else
{
pWaitForVerticalBlank->bIsInVB = FALSE;
}
}
}
}
LEAVE_BOTH();
return dwRet;
}
void BuildSurfaceDesc( PD3D8_CREATESURFACEDATA pCreateSurface, DDSURFACEDESC2* pddsd2 )
{
PDDDEVICEHANDLE pDevice = (PDDDEVICEHANDLE) pCreateSurface->hDD;
LPDDRAWI_DIRECTDRAW_INT pdrv_int = pDevice->pDD;
HRESULT hr;
DWORD i;
PDDSURFACE pSurf;
LPDIRECTDRAWSURFACE lpDDSurface;
memset(pddsd2, 0, sizeof(DDSURFACEDESC2));
pddsd2->dwSize = sizeof( DDSURFACEDESC2 );
//dwCaps3==1 means 1 sample per pixel.
pddsd2->ddsCaps.dwCaps3 = DDSCAPS3_MULTISAMPLE_MASK & (DWORD) pCreateSurface->MultiSampleType;
// Convert all of the caps
switch (pCreateSurface->Type)
{
case D3DRTYPE_SURFACE:
if (pCreateSurface->dwUsage & D3DUSAGE_ALPHACHANNEL)
{
DPF(0,"Setting alphachannel");
pddsd2->ddsCaps.dwCaps2 |= DDSCAPS2_ENABLEALPHACHANNEL;
}
if (pCreateSurface->dwUsage & D3DUSAGE_PRIMARYSURFACE)
{
// If we aren't creating a primary flip chain, then we
// don't have to do much here.
if (pCreateSurface->dwSCnt == 1)
{
pddsd2->ddsCaps.dwCaps |= DDSCAPS_PRIMARYSURFACE;
}
else
{
pddsd2->ddsCaps.dwCaps |= DDSCAPS_PRIMARYSURFACE |
DDSCAPS_COMPLEX |
DDSCAPS_FLIP |
DDSCAPS_3DDEVICE;
}
}
else if (pCreateSurface->dwUsage & D3DUSAGE_DEPTHSTENCIL)
{
DDASSERT(0 == (pCreateSurface->dwUsage & D3DUSAGE_DISCARD) );
pddsd2->ddsCaps.dwCaps |= DDSCAPS_ZBUFFER;
}
else
{
pddsd2->ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN;
}
if (pCreateSurface->dwSCnt > 1)
{
pddsd2->dwBackBufferCount = pCreateSurface->dwSCnt - 1;
pddsd2->dwFlags |= DDSD_BACKBUFFERCOUNT;
pddsd2->ddsCaps.dwCaps |= DDSCAPS_COMPLEX;
}
break;
case D3DRTYPE_TEXTURE:
DDASSERT(0 == (pCreateSurface->dwUsage & D3DUSAGE_DISCARD) );
if (pCreateSurface->dwSCnt > 1)
{
pddsd2->ddsCaps.dwCaps |= DDSCAPS_TEXTURE | DDSCAPS_MIPMAP | DDSCAPS_COMPLEX;
pddsd2->dwFlags |= DDSD_MIPMAPCOUNT;
pddsd2->dwMipMapCount = pCreateSurface->dwSCnt;
}
else
{
// To DDraw, a mipmap w/ one level is really only a texture
pddsd2->ddsCaps.dwCaps |= DDSCAPS_TEXTURE;
}
if (pCreateSurface->dwUsage & D3DUSAGE_DYNAMIC)
{
pddsd2->ddsCaps.dwCaps2 |= DDSCAPS2_HINTDYNAMIC;
}
break;
case D3DRTYPE_CUBETEXTURE:
DDASSERT(0 == (pCreateSurface->dwUsage & D3DUSAGE_DISCARD) );
pddsd2->ddsCaps.dwCaps |= DDSCAPS_TEXTURE | DDSCAPS_COMPLEX;
pddsd2->ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP;
pddsd2->ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_ALLFACES;
DDASSERT(pCreateSurface->dwSCnt >= 6);
DDASSERT((pCreateSurface->dwSCnt % 6) == 0);
if (pCreateSurface->dwSCnt > 6)
{
pddsd2->ddsCaps.dwCaps |= DDSCAPS_MIPMAP;
pddsd2->dwFlags |= DDSD_MIPMAPCOUNT;
pddsd2->dwMipMapCount = pCreateSurface->dwSCnt / 6;
}
if (pCreateSurface->dwUsage & D3DUSAGE_DYNAMIC)
{
pddsd2->ddsCaps.dwCaps2 |= DDSCAPS2_HINTDYNAMIC;
}
break;
case D3DRTYPE_IMAGESURFACE:
DDASSERT(0 == (pCreateSurface->dwUsage & D3DUSAGE_DISCARD) );
// Image surfaces are marked as textures since they have the
// greatest flexibility for formats. But they don't get
// a CreateSurfaceEx handle since they are never passed to
// a driver.
pddsd2->ddsCaps.dwCaps |= DDSCAPS_TEXTURE;
break;
case D3DRTYPE_COMMANDBUFFER:
pddsd2->ddsCaps.dwCaps |= DDSCAPS_EXECUTEBUFFER;
pddsd2->ddsCaps.dwCaps2 |= DDSCAPS2_COMMANDBUFFER;
DDASSERT(0 == (pCreateSurface->dwUsage & D3DUSAGE_DISCARD) );
DDASSERT((pCreateSurface->dwUsage & D3DUSAGE_INTERNALBUFFER) == 0);
break;
case D3DRTYPE_VERTEXBUFFER:
DDASSERT(0 == (pCreateSurface->dwUsage & D3DUSAGE_DISCARD) );
pddsd2->ddsCaps.dwCaps |= DDSCAPS_EXECUTEBUFFER;
if (!(pCreateSurface->dwUsage & D3DUSAGE_INTERNALBUFFER))
{
pddsd2->ddsCaps.dwCaps2 |= DDSCAPS2_VERTEXBUFFER;
}
if (pDevice->DriverLevel >= 8)
{
if (pCreateSurface->dwUsage & D3DUSAGE_DYNAMIC)
{
pddsd2->ddsCaps.dwCaps2 |= DDSCAPS2_HINTDYNAMIC;
}
else
{
pddsd2->ddsCaps.dwCaps2 |= DDSCAPS2_HINTSTATIC;
}
}
break;
case D3DRTYPE_INDEXBUFFER:
DDASSERT(0 == (pCreateSurface->dwUsage & D3DUSAGE_DISCARD) );
pddsd2->ddsCaps.dwCaps |= DDSCAPS_EXECUTEBUFFER;
pddsd2->ddsCaps.dwCaps2 |= DDSCAPS2_INDEXBUFFER;
if (pDevice->DriverLevel >= 8)
{
if (pCreateSurface->dwUsage & D3DUSAGE_DYNAMIC)
{
pddsd2->ddsCaps.dwCaps2 |= DDSCAPS2_HINTDYNAMIC;
}
else
{
pddsd2->ddsCaps.dwCaps2 |= DDSCAPS2_HINTSTATIC;
}
}
break;
case D3DRTYPE_VOLUME:
// We don't create stand-alone volumes
DDASSERT(FALSE);
break;
case D3DRTYPE_VOLUMETEXTURE:
DDASSERT(0 == (pCreateSurface->dwUsage & D3DUSAGE_DISCARD) );
pddsd2->ddsCaps.dwCaps |= DDSCAPS_TEXTURE | DDSCAPS_MIPMAP;
pddsd2->ddsCaps.dwCaps2 |= DDSCAPS2_VOLUME;
pddsd2->ddsCaps.dwCaps4 =
MAKELONG((WORD)(pCreateSurface->pSList[0].cpDepth),0);
if (pCreateSurface->dwSCnt > 1)
{
pddsd2->ddsCaps.dwCaps |= DDSCAPS_COMPLEX;
pddsd2->dwFlags |= DDSD_MIPMAPCOUNT;
}
pddsd2->dwMipMapCount = pCreateSurface->dwSCnt;
if (pCreateSurface->dwUsage & D3DUSAGE_DYNAMIC)
{
pddsd2->ddsCaps.dwCaps2 |= DDSCAPS2_HINTDYNAMIC;
}
break;
}
if (pCreateSurface->dwUsage & D3DUSAGE_RENDERTARGET)
{
pddsd2->ddsCaps.dwCaps |= DDSCAPS_3DDEVICE;
}
if (pCreateSurface->dwUsage & D3DUSAGE_DEPTHSTENCIL)
{
pddsd2->ddsCaps.dwCaps |= DDSCAPS_ZBUFFER;
}
if (pDevice->DriverLevel >= 8)
{
if (pCreateSurface->dwUsage & D3DUSAGE_LOADONCE)
{
pddsd2->ddsCaps.dwCaps2 |= DDSCAPS2_OPAQUE;
}
if (pCreateSurface->dwUsage & D3DUSAGE_WRITEONLY)
{
pddsd2->ddsCaps.dwCaps |= DDSCAPS_WRITEONLY;
}
// Specify new usages for DX8+ drivers
if (!(pCreateSurface->dwUsage & D3DUSAGE_LOCK) &&
!(pCreateSurface->dwUsage & D3DUSAGE_LOADONCE))
{
pddsd2->ddsCaps.dwCaps2 |= DDSCAPS2_NOTUSERLOCKABLE;
}
if (pCreateSurface->dwUsage & D3DUSAGE_DISCARD)
{
DDASSERT(pCreateSurface->Type != D3DRTYPE_TEXTURE);
DDASSERT(pCreateSurface->Type != D3DRTYPE_CUBETEXTURE);
DDASSERT(pCreateSurface->Type != D3DRTYPE_VOLUMETEXTURE);
DDASSERT(pCreateSurface->Type != D3DRTYPE_VOLUME);
DDASSERT(pCreateSurface->Type != D3DRTYPE_VERTEXBUFFER);
DDASSERT(pCreateSurface->Type != D3DRTYPE_INDEXBUFFER);
pddsd2->ddsCaps.dwCaps2 |= DDSCAPS2_DISCARDBACKBUFFER;
}
if (pCreateSurface->dwUsage & D3DUSAGE_POINTS)
{
pddsd2->ddsCaps.dwCaps2 |= DDSCAPS2_POINTS;
}
if (pCreateSurface->dwUsage & D3DUSAGE_RTPATCHES)
{
pddsd2->ddsCaps.dwCaps2 |= DDSCAPS2_RTPATCHES;
}
if (pCreateSurface->dwUsage & D3DUSAGE_NPATCHES)
{
pddsd2->ddsCaps.dwCaps2 |= DDSCAPS2_NPATCHES;
}
}
else // Pre-DX8 driver
{
// We allow LOADONCE through only for textures
if ((pCreateSurface->Type == D3DRTYPE_TEXTURE) ||
(pCreateSurface->Type == D3DRTYPE_CUBETEXTURE) ||
(pCreateSurface->Type == D3DRTYPE_VOLUMETEXTURE) ||
(pCreateSurface->Type == D3DRTYPE_VOLUME))
{
if (pCreateSurface->dwUsage & D3DUSAGE_LOADONCE)
{
pddsd2->ddsCaps.dwCaps2 |= DDSCAPS2_OPAQUE;
}
}
// We allow WRITEONLY through only for VBs
if (pCreateSurface->Type == D3DRTYPE_VERTEXBUFFER)
{
if (pCreateSurface->dwUsage & D3DUSAGE_WRITEONLY)
{
pddsd2->ddsCaps.dwCaps |= DDSCAPS_WRITEONLY;
}
}
}
switch (pCreateSurface->Pool)
{
case D3DPOOL_LOCALVIDMEM:
pddsd2->ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY;
break;
case D3DPOOL_NONLOCALVIDMEM:
pddsd2->ddsCaps.dwCaps |= DDSCAPS_NONLOCALVIDMEM | DDSCAPS_VIDEOMEMORY;
break;
case D3DPOOL_SYSTEMMEM:
pddsd2->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
break;
case D3DPOOL_MANAGED:
// We should only see this for DX8+ drivers <kd>
DDASSERT(pDevice->DriverLevel >= 8);
pddsd2->ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
pddsd2->ddsCaps.dwCaps2 |= DDSCAPS2_TEXTUREMANAGE;
break;
case D3DPOOL_DEFAULT:
pCreateSurface->Pool = D3DPOOL_LOCALVIDMEM;
pddsd2->ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
break;
default:
/* Unknown Pool?? */
DDASSERT(FALSE);
break;
}
pddsd2->dwFlags |= DDSD_CAPS;
// Convert the pixel format:
if ((pCreateSurface->Format != D3DFMT_UNKNOWN) &&
(pCreateSurface->Format != D3DFMT_VERTEXDATA) &&
(pCreateSurface->Format != D3DFMT_INDEX16) &&
(pCreateSurface->Format != D3DFMT_INDEX32) &&
!(pddsd2->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE))
{
pddsd2->dwFlags |= DDSD_PIXELFORMAT;
// For non-textures, we want to promote X8R8G8B8 to A8R8G8B8 in some cases;
// this allows things like RTs and Backbuffers to get created matching the
// primary which is more consistent with typical DX7 usage.
if (FormatCompatibleWithDisplayFormat(pDevice, (D3DFORMAT)pCreateSurface->Format) &&
(pCreateSurface->Type == D3DRTYPE_SURFACE))
{
//Surface looks like primary:
ConvertToOldFormat(&pddsd2->ddpfPixelFormat, pDevice->DisplayFormatWithAlpha);
}
else
{
ConvertToOldFormat(&pddsd2->ddpfPixelFormat, (D3DFORMAT)pCreateSurface->Format);
}
}
if (!(pddsd2->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE))
{
pddsd2->dwHeight = pCreateSurface->pSList[0].cpHeight;
pddsd2->dwWidth = pCreateSurface->pSList[0].cpWidth;
pddsd2->dwFlags |= DDSD_HEIGHT | DDSD_WIDTH;
if (pddsd2->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER)
{
pddsd2->dwHeight = 0;
pddsd2->dwFlags &= ~DDSD_HEIGHT;
}
}
if (pCreateSurface->Type == D3DRTYPE_VERTEXBUFFER)
{
pddsd2->dwFVF = pCreateSurface->dwFVF;
pddsd2->dwFlags |= DDSD_FVF;
}
if (pddsd2->ddsCaps.dwCaps2 & DDSCAPS2_VOLUME)
{
pddsd2->dwDepth = pCreateSurface->pSList[0].cpDepth;
pddsd2->dwFlags |= DDSD_DEPTH;
}
}
DWORD InitSoftwareSurface(PD3D8_CREATESURFACEDATA pCreateSurface,
DWORD SurfIndex,
DDSURFACEDESC2* pddsd2,
DDSURFACE* pSurf,
DDSURFACE* pPrevious)
{
LPDDRAWI_DDRAWSURFACE_INT pInt;
LPDDRAWI_DDRAWSURFACE_LCL pLcl;
BYTE * pTemp;
PDDDEVICEHANDLE pDevice = (PDDDEVICEHANDLE) pCreateSurface->hDD;
pInt = MemAlloc( sizeof(DDRAWI_DDRAWSURFACE_LCL) +
sizeof(DDRAWI_DDRAWSURFACE_GBL) +
sizeof(DDRAWI_DDRAWSURFACE_MORE) +
sizeof(DDRAWI_DDRAWSURFACE_INT));
if (pInt == NULL)
{
return DDERR_OUTOFMEMORY;
}
pTemp = (BYTE*) pInt;
pTemp += sizeof(DDRAWI_DDRAWSURFACE_INT);
pInt->lpLcl = (LPDDRAWI_DDRAWSURFACE_LCL) pTemp;
pLcl = pInt->lpLcl;
pTemp += sizeof(DDRAWI_DDRAWSURFACE_LCL);
pLcl->lpGbl = (LPDDRAWI_DDRAWSURFACE_GBL) pTemp;
pTemp += sizeof(DDRAWI_DDRAWSURFACE_GBL);
pLcl->lpSurfMore = (LPDDRAWI_DDRAWSURFACE_MORE) pTemp;
memcpy(&pInt->lpLcl->lpGbl->ddpfSurface, &pddsd2->ddpfPixelFormat, sizeof(DDPIXELFORMAT));
if (pddsd2->dwFlags & DDSD_PIXELFORMAT)
{
pLcl->dwFlags |= DDRAWISURF_HASPIXELFORMAT;
}
pLcl->lpGbl->wWidth = (WORD) pCreateSurface->pSList[SurfIndex].cpWidth;
pLcl->lpGbl->wHeight = (WORD) pCreateSurface->pSList[SurfIndex].cpHeight;
pLcl->ddsCaps.dwCaps = pddsd2->ddsCaps.dwCaps;
pLcl->lpSurfMore->ddsCapsEx.dwCaps2 = pddsd2->ddsCaps.dwCaps2;
pLcl->lpSurfMore->ddsCapsEx.dwCaps3 = DDSCAPS3_MULTISAMPLE_MASK & (DWORD) pCreateSurface->MultiSampleType;
pLcl->lpSurfMore->ddsCapsEx.dwCaps4 = pddsd2->ddsCaps.dwCaps4;
pLcl->lpSurfMore->dwSurfaceHandle = pSurf->dwCookie;
pLcl->lpSurfMore->lpDD_lcl = pDevice->pSwDD->lpLcl;
if (pSurf->Pool == D3DPOOL_SYSTEMMEM)
{
pLcl->lpGbl->fpVidMem = (FLATPTR) pCreateSurface->pSList[SurfIndex].pbPixels;
pLcl->lpGbl->lPitch = pCreateSurface->pSList[SurfIndex].iPitch;
}
if ((pCreateSurface->Type == D3DRTYPE_VOLUME) ||
(pCreateSurface->Type == D3DRTYPE_VOLUMETEXTURE))
{
pLcl->lpGbl->lSlicePitch = pCreateSurface->pSList[SurfIndex].iSlicePitch;
pLcl->lpSurfMore->ddsCapsEx.dwCaps4 =
MAKELONG((WORD)(pCreateSurface->pSList[SurfIndex].cpDepth),0);
}
// If it is a cube-map face, fix up the face flags in caps2.
if (pCreateSurface->Type == D3DRTYPE_CUBETEXTURE)
{
int MipLevels;
if (pCreateSurface->dwSCnt>6)
pLcl->ddsCaps.dwCaps |= DDSCAPS_MIPMAP;
MipLevels = pCreateSurface->dwSCnt/6; //since all faces are always present in DX8
DDASSERT(MipLevels>=1);
//the first n (where n is mip depth) faces are +x, etc.
pLcl->lpSurfMore->ddsCapsEx.dwCaps2 |= DDSCAPS2_CUBEMAP;
pLcl->lpSurfMore->ddsCapsEx.dwCaps2 &= ~(DDSCAPS2_CUBEMAP_ALLFACES);
pLcl->lpSurfMore->ddsCapsEx.dwCaps2 |=
dwOrderedFaces[SurfIndex/MipLevels];
//every MipLevels'th surface is a top-level face,
if (SurfIndex % MipLevels)
{
// Mark non-top levels as being a sub-level
pLcl->lpSurfMore->ddsCapsEx.dwCaps2 |= DDSCAPS2_MIPMAPSUBLEVEL;
}
}
// If it is a texture, fix up the flags in caps2.
else if ((pCreateSurface->Type == D3DRTYPE_TEXTURE) ||
(pCreateSurface->Type == D3DRTYPE_VOLUMETEXTURE) ||
(pCreateSurface->Type == D3DRTYPE_VOLUME))
{
if( SurfIndex > 0 )
{
pLcl->lpSurfMore->ddsCapsEx.dwCaps2 |= DDSCAPS2_MIPMAPSUBLEVEL;
}
}
pSurf->pTempHeavy = pInt;
return DD_OK;
}
/*****************************Private*Routine******************************\
* SelectAttachmentSurface
*
* Returns an index into the surface creation list that indicates which
* surface this surface should be attached to. For mipmap sublevels this is
* always the preceding surface. For cubemaps, each face attaches to the
* root face (element 0).
*
* History:
* 21-Mar-2000 -by- Jeff Noyle [jeffno]
* Wrote it.
\**************************************************************************/
#undef DPF_MODNAME
#define DPF_MODNAME "SelectAttachmentSurface"
UINT SelectAttachmentSurface(
PD3D8_CREATESURFACEDATA pCreateSurface,
UINT iThis)
{
//We should never be called to find the attachment from the root face.
DDASSERT( iThis > 0);
if ((pCreateSurface->Type == D3DRTYPE_CUBETEXTURE) &&
((iThis % (pCreateSurface->dwSCnt/6)) == 0) //which means we're looking at a top-level face
)
{
//... so we attach this face to the root
return 0;
}
else
{
// nope its just a mip sublevel, so we attach to the previous
return iThis-1;
}
}
void ExtractLightweightInfo (DDSURFACE *pSurf, LPDDRAWI_DDRAWSURFACE_INT pInt)
{
LIGHTWEIGHTSURFACE* pLight = pSurf->Surface.pLight;
LPDDRAWI_DDRAWSURFACE_GBL_MORE lpGblMore;
pLight->LclFlags = pInt->lpLcl->dwFlags;
pLight->LclCaps1 = pInt->lpLcl->ddsCaps.dwCaps;
pLight->LclReserved1 = pInt->lpLcl->dwReserved1;
pLight->LclModeCreatedIn = pInt->lpLcl->dwModeCreatedIn;
pLight->LclBackBufferCount = pInt->lpLcl->dwBackBufferCount;
pLight->GblFlags = pInt->lpLcl->lpGbl->dwGlobalFlags;
pLight->GblPitch = pInt->lpLcl->lpGbl->lPitch;
if (pSurf->Pitch == 0)
{
pSurf->Pitch = pLight->GblPitch;
}
pLight->GblWidth = pInt->lpLcl->lpGbl->wWidth;
pLight->GblReserved1 = pInt->lpLcl->lpGbl->dwReserved1;
if (pLight->LclFlags & DDRAWISURF_HASPIXELFORMAT)
{
ConvertFromOldFormat(&pInt->lpLcl->lpGbl->ddpfSurface,
&pLight->GblFormat);
}
else
{
pLight->GblFormat = D3DFMT_UNKNOWN;
}
pLight->pGblVidMemHeap = pInt->lpLcl->lpGbl->lpVidMemHeap;
pLight->fpGblVidMem = pInt->lpLcl->lpGbl->fpVidMem;
pLight->MoreCaps2 = pInt->lpLcl->lpSurfMore->ddsCapsEx.dwCaps2;
pLight->MoreCaps3 = pInt->lpLcl->lpSurfMore->ddsCapsEx.dwCaps3;
pLight->MoreCaps4 = pInt->lpLcl->lpSurfMore->ddsCapsEx.dwCaps4;
pLight->MoreRgjunc = pInt->lpLcl->lpSurfMore->rgjunc;
if ((pLight->LclCaps1 & DDSCAPS_MIPMAP) ||
(pLight->MoreCaps2 & DDSCAPS2_VOLUME))
{
pLight->MoreMipMapCount = pInt->lpLcl->lpSurfMore->dwMipMapCount;
}
else
{
pLight->MoreFVF = pInt->lpLcl->lpSurfMore->dwFVF;
}
lpGblMore = GET_LPDDRAWSURFACE_GBL_MORE (pInt->lpLcl->lpGbl);
if (lpGblMore != NULL)
{
pLight->GblMoreDriverReserved = lpGblMore->dwDriverReserved;
pLight->GblMoreContentsStamp = lpGblMore->dwContentsStamp;
pLight->pGblMoreUnswappedDriverReserved = lpGblMore->lpvUnswappedDriverReserved;
pLight->fpGblMoreAliasOfVidMem = lpGblMore->fpAliasOfVidMem;
pLight->cGblMorePageUnlocks = lpGblMore->cPageUnlocks;
}
if (pLight->LclCaps1 & DDSCAPS_NONLOCALVIDMEM)
{
if (lpGblMore != NULL)
{
pLight->fpGblMorePhysicalVidMem = lpGblMore->fpPhysicalVidMem;
}
}
else if (pLight->LclCaps1 & DDSCAPS_LOCALVIDMEM)
{
if (lpGblMore != NULL)
{
pLight->fpGblMoreAliasedVidMem = lpGblMore->fpAliasedVidMem;
}
}
else
{
pLight->MoreBytesAllocated = pInt->lpLcl->lpSurfMore->dwBytesAllocated;
}
pSurf->Height = pInt->lpLcl->lpGbl->wHeight;
pSurf->dwCookie = pInt->lpLcl->lpSurfMore->dwSurfaceHandle;
}
void DiscardHeavyweightMemory( LPDDRAWI_DDRAWSURFACE_INT pInt)
{
if (pInt->lpLcl->lpSurfMore->slist != NULL)
{
MemFree (pInt->lpLcl->lpSurfMore->slist);
}
MemFree (pInt->lpLcl);
MemFree (pInt);
}
DWORD APIENTRY DdCreateSurface( PD3D8_CREATESURFACEDATA pCreateSurface )
{
PDDDEVICEHANDLE pDevice = (PDDDEVICEHANDLE) pCreateSurface->hDD;
LPDDRAWI_DIRECTDRAW_INT pdrv_int = pDevice->pDD;
HRESULT hr;
DWORD i;
PDDSURFACE pSurf;
LPDIRECTDRAWSURFACE lpDDSurface;
DWORD dwNumToCreate;
DDSURFACEDESC2 ddsd2;
DWORD NextWidth;
DWORD NextHeight;
DEFERREDCREATE* pDefCreate;
ENTER_DDRAW();
BuildSurfaceDesc (pCreateSurface, &ddsd2);
dwNumToCreate = pCreateSurface->dwSCnt;
// Allocate the internal surface structures for each surface in the chain
// and initialize it if we are not reusing the surface
if (!pCreateSurface->bReUse)
{
NextWidth = ddsd2.dwWidth;
NextHeight = ddsd2.dwHeight;
for (i = 0; i < dwNumToCreate; i++)
{
pSurf = (PDDSURFACE) MemAlloc(sizeof(DDSURFACE));
if (pSurf == NULL)
{
hr = DDERR_OUTOFMEMORY;
goto CreateErrorCleanup;
}
pSurf->Pool = pCreateSurface->Pool;
pSurf->Format = pCreateSurface->Format;
pSurf->Type = pCreateSurface->Type;
// For volume textures, we need to know the depth to handle lost
// devices (for everything else we need to height). To save space,
// we will re-use the same variable.
if ((pSurf->Type == D3DRTYPE_VOLUME) ||
(pSurf->Type == D3DRTYPE_VOLUMETEXTURE))
{
pSurf->Height = pCreateSurface->pSList[i].cpDepth;
}
else
{
pSurf->Height = pCreateSurface->pSList[i].cpHeight;
}
pCreateSurface->pSList[i].hKernelHandle = (HANDLE) pSurf;
pSurf->pDevice = (PDDDEVICEHANDLE) pCreateSurface->hDD;
// DX6 drivers cannot handle deep mipmaps, but we want to hide this from
// the runtime, so we need to determine if the current level is a dummy
// level
if ((pDevice->DriverLevel == 6) &&
(ddsd2.ddsCaps.dwCaps & DDSCAPS_MIPMAP))
{
if ((pCreateSurface->pSList[i].cpWidth == NextWidth) &&
(pCreateSurface->pSList[i].cpHeight == NextHeight))
{
// This level is OK, so mark it as such
ddsd2.dwMipMapCount = i + 1;
}
else
{
pSurf->dwFlags |= DDSURFACE_DUMMY;
if (i == 1)
{
// If there's only one valid level, then don't call it
// a mipmap
ddsd2.ddsCaps.dwCaps &= ~DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
ddsd2.dwFlags &= ~DDSD_MIPMAPCOUNT;
}
}
NextWidth /= 2;
NextHeight /= 2;
}
// Now figure out if this is a software driver
// surface, or a HAL surface.
if (IS_SOFTWARE_DRIVER(pCreateSurface->hDD) &&
!(pCreateSurface->dwUsage & D3DUSAGE_PRIMARYSURFACE) &&
!(pCreateSurface->dwUsage & D3DUSAGE_OFFSCREENPLAIN))
{
// If they are running w/ a software driver (refrast, RGB HEL, etc.),
// we will not allow any surfaces to be created in video memory except
// for the primary flipping chain. And also for surfaces marked
// D3DUSAGE_OFFSCREENPLAIN (which are used for the cursors)
pSurf->dwFlags |= DDSURFACE_SOFTWARE;
}
else
{
pSurf->dwFlags |= DDSURFACE_HAL;
}
if (pCreateSurface->bTreatAsVidMem == TRUE)
{
// For objects that should be treated as non-persistent
// i.e. Reset fails unless these are all freed; we
// set a flag here and check it in DoVidMemSurfacesExist()
pSurf->dwFlags |= DDSURFACE_TREATASVIDMEM;
}
if (pDevice->bLightweight && IsLightweightSurface(pDevice, &ddsd2, pCreateSurface->Format))
{
pSurf->dwFlags |= DDSURFACE_LIGHTWEIGHT;
pSurf->Surface.pLight = (LIGHTWEIGHTSURFACE*) MemAlloc(sizeof(LIGHTWEIGHTSURFACE));
if (pSurf->Surface.pLight == NULL)
{
hr = DDERR_OUTOFMEMORY;
goto CreateErrorCleanup;
}
}
else
{
pSurf->dwFlags |= DDSURFACE_HEAVYWEIGHT;
}
// Software surfaces are special cased because we want to call the software
// driver for Create and CreateEx rather than the real driver.
if (IS_SOFTWARE_DRIVER_SURFACE(pSurf))
{
if ((ddsd2.ddsCaps.dwCaps & (DDSCAPS_TEXTURE |
DDSCAPS_EXECUTEBUFFER |
DDSCAPS_3DDEVICE |
DDSCAPS_ZBUFFER)) &&
(pCreateSurface->Type != D3DRTYPE_IMAGESURFACE))
{
pSurf->dwCookie = GetDX7SurfaceHandle(pCreateSurface->hDD);
}
hr = InitSoftwareSurface(pCreateSurface,
i,
&ddsd2,
pSurf,
i > 0 ? pCreateSurface->pSList[i].hKernelHandle : NULL);
if (hr != DD_OK)
{
goto CreateErrorCleanup;
}
}
}
}
else
{
DDASSERT(pCreateSurface->Pool == D3DPOOL_MANAGED);
}
pSurf = (DDSURFACE*) pCreateSurface->pSList[0].hKernelHandle;
if (IS_SOFTWARE_DRIVER_SURFACE(pSurf))
{
if (pCreateSurface->Pool != D3DPOOL_SYSTEMMEM)
{
// There is a descrepancy in the surface desc that CreateSurface
// expects and the driver expects, so we will adjust it here for
// the driver.
if ((ddsd2.dwFlags & DDSD_WIDTH) &&
!(ddsd2.dwFlags & DDSD_HEIGHT))
{
ddsd2.dwFlags |= DDSD_HEIGHT;
ddsd2.dwHeight = 1;
}
hr = SwDDICreateSurface(pCreateSurface, &ddsd2);
if (hr != DD_OK)
{
goto CreateErrorCleanup;
}
for (i = 0; i < pCreateSurface->dwSCnt; i++)
{
((DDSURFACE*)pCreateSurface->pSList[i].hKernelHandle)->dwFlags |=
DDSURFACE_CREATECOMPLETE;
}
}
// We've already created the object so all
// we have to do is call CreateSurfaceEx
if (pSurf->dwCookie != 0)
{
// If it's a software driver, we may need to attach surfaces
for (i = 1; i < pCreateSurface->dwSCnt; i++)
{
SwDDIAttachSurfaces (
((DDSURFACE*)pCreateSurface->pSList[
SelectAttachmentSurface(pCreateSurface,i)
].hKernelHandle)->pTempHeavy->lpLcl,
((DDSURFACE*)pCreateSurface->pSList[i].hKernelHandle)->pTempHeavy->lpLcl);
}
SwDDICreateSurfaceEx (pDevice->pSwDD->lpLcl,
pSurf->pTempHeavy->lpLcl);
pSurf->dwFlags |= DDSURFACE_CREATEEX;
}
for (i = 0; i < pCreateSurface->dwSCnt; i++)
{
LPATTACHLIST pAttach;
LPATTACHLIST pAttachTemp;
pSurf = (DDSURFACE*)pCreateSurface->pSList[i].hKernelHandle;
// For a sw driver, always destroy the attached list now.
// It serves no purpose after CreateSurfaceEx is called.
if (pSurf->pTempHeavy->lpLcl->lpAttachList != NULL)
{
pAttach = pSurf->pTempHeavy->lpLcl->lpAttachList->lpLink;
while (pAttach != NULL)
{
pAttachTemp = pAttach;
pAttach = pAttach->lpLink;
MemFree(pAttachTemp);
}
MemFree(pSurf->pTempHeavy->lpLcl->lpAttachList);
pSurf->pTempHeavy->lpLcl->lpAttachList = NULL;
}
if (pSurf->pTempHeavy->lpLcl->lpAttachListFrom != NULL)
{
pAttach = pSurf->pTempHeavy->lpLcl->lpAttachListFrom->lpLink;
while (pAttach != NULL)
{
pAttachTemp = pAttach;
pAttach = pAttach->lpLink;
MemFree(pAttachTemp);
}
MemFree(pSurf->pTempHeavy->lpLcl->lpAttachListFrom);
pSurf->pTempHeavy->lpLcl->lpAttachListFrom = NULL;
}
pSurf->iSlicePitch = pSurf->pTempHeavy->lpLcl->lpGbl->lSlicePitch;
pSurf->pTempHeavy->lpLcl->lpGbl->lSlicePitch = 0;
if (pSurf->dwFlags & DDSURFACE_LIGHTWEIGHT)
{
ExtractLightweightInfo (pSurf, pSurf->pTempHeavy);
MemFree (pSurf->pTempHeavy);
}
else
{
pSurf->Surface.pHeavy = pSurf->pTempHeavy;
}
pSurf->pTempHeavy = NULL;
}
}
else
{
LPDDSURFACEINFO pSysMem = NULL;
BOOL bLost;
// If it's a sysmem surface, we want them to use the memory that we
// have already allocated, so we need to setup an array of pointers.
if ((pCreateSurface->Pool == D3DPOOL_SYSTEMMEM) ||
(ddsd2.ddsCaps.dwCaps2 & DDSCAPS2_VOLUME))
{
pSysMem = pCreateSurface->pSList;
}
// If we are creating a vidmem surface, we need to check for device lost
// and if it's lost, we don't want to create the surface, but to instead
// allocate a private buffer that we can return when lock is called. We
// do not want to fail the call just because the device is lost.
ENTER_WIN16LOCK();
bLost = CheckForDeviceLost(pDevice);
// Special early out. If reuse is true, we haven't done anything yet (to
// verify this, trace code above) so all we need to do is to return SURFACELOST
// and not worry about jumping to CreateErrorCleanup below.
if (bLost && pCreateSurface->bReUse)
{
DDASSERT(!IS_SOFTWARE_DRIVER_SURFACE(pSurf));
DDASSERT(pCreateSurface->Pool == D3DPOOL_MANAGED);
LEAVE_WIN16LOCK();
LEAVE_DDRAW();
return DDERR_SURFACELOST;
}
if ((pCreateSurface->Pool != D3DPOOL_SYSTEMMEM) &&
bLost)
{
DWORD j;
DDASSERT(pCreateSurface->bReUse == FALSE);
for (i = 0; i < pCreateSurface->dwSCnt; i++)
{
pSurf = (PDDSURFACE) pCreateSurface->pSList[i].hKernelHandle;
pSurf->Pitch = pCreateSurface->pSList[i].cpWidth * 8;
pSurf->iSlicePitch = pSurf->Pitch * pCreateSurface->pSList[i].cpHeight;
if (!(pSurf->dwFlags & DDSURFACE_DUMMY))
{
if ((pSurf->Type == D3DRTYPE_VOLUME) ||
(pSurf->Type == D3DRTYPE_VOLUMETEXTURE))
{
pSurf->fpVidMem = (char*)
MemAlloc(pSurf->iSlicePitch * pSurf->Height);
}
else
{
pSurf->fpVidMem = (char*)
MemAlloc(pSurf->Pitch * pSurf->Height);
}
if (pSurf->fpVidMem == (char*) NULL)
{
DWORD j;
for (j = 0; j < i; j++)
{
pSurf = (PDDSURFACE) pCreateSurface->pSList[i].hKernelHandle;
MemFree (pSurf->fpVidMem);
}
hr = DDERR_OUTOFMEMORY;
LEAVE_WIN16LOCK();
goto CreateErrorCleanup;
}
else
{
pSurf->dwFlags |= DDSURFACE_SYSMEMALLOCATED;
}
}
}
// If the surface is driver managed, we save the creation info so that
// we can retry the creation at reset time
if (ddsd2.ddsCaps.dwCaps2 & DDSCAPS2_TEXTUREMANAGE)
{
DDASSERT(pCreateSurface->Pool == D3DPOOL_MANAGED);
pDefCreate = (PDEFERREDCREATE)MemAlloc(sizeof(DEFERREDCREATE));
if (pDefCreate == NULL)
{
// Cleanup stuff that we allocated above
for (i = 0; i < pCreateSurface->dwSCnt; ++i)
{
pSurf = (PDDSURFACE) pCreateSurface->pSList[i].hKernelHandle;
MemFree(pSurf->fpVidMem);
pSurf->dwFlags &= ~DDSURFACE_SYSMEMALLOCATED;
}
hr = DDERR_OUTOFMEMORY;
LEAVE_WIN16LOCK();
goto CreateErrorCleanup;
}
// Copy
pDefCreate->CreateData = *pCreateSurface;
pDefCreate->CreateData.pSList = (LPDDSURFACEINFO)MemAlloc(sizeof(DDSURFACEINFO) * pCreateSurface->dwSCnt);
if (pDefCreate->CreateData.pSList == NULL)
{
// Cleanup stuff that we allocated above
MemFree(pDefCreate);
for (i = 0; i < pCreateSurface->dwSCnt; ++i)
{
pSurf = (PDDSURFACE) pCreateSurface->pSList[i].hKernelHandle;
MemFree(pSurf->fpVidMem);
pSurf->dwFlags &= ~DDSURFACE_SYSMEMALLOCATED;
}
hr = DDERR_OUTOFMEMORY;
LEAVE_WIN16LOCK();
goto CreateErrorCleanup;
}
// Copy
CopyMemory(pDefCreate->CreateData.pSList, pCreateSurface->pSList, sizeof(DDSURFACEINFO) * pCreateSurface->dwSCnt);
// Linkup
pDefCreate->pNext = ((PDDDEVICEHANDLE)pCreateSurface->hDD)->pDeferList;
((PDDDEVICEHANDLE)pCreateSurface->hDD)->pDeferList = pDefCreate;
// *************************MEMORY LEAK WARNING*********************** //
// The DEFERREDCREATE and DDSURFACEINFO allocations above will
// not be cleaned up immediately if there is a failure after this
// point. As of 5/2001, there is no case in which we will fail after
// this point. (snene)
// ******************************************************************* //
}
}
else
{
DWORD DX8Flags = DX8SFLAG_DX8;
// If we are creating a sysmem surface while lost, we don't want
// want to call the driver to create the SurfaceEx handle.
if (bLost)
{
DX8Flags |= DX8SFLAG_ISLOST;
}
if (pSurf->dwFlags & DDSURFACE_LIGHTWEIGHT)
{
DX8Flags |= DX8SFLAG_ISLIGHTWEIGHT;
}
if (pCreateSurface->Type == D3DRTYPE_IMAGESURFACE)
{
DX8Flags |= DX8SFLAG_IMAGESURF;
}
hr = DD_CreateSurface4_Main( (LPDIRECTDRAW) pdrv_int,
&ddsd2,
&lpDDSurface,
NULL,
TRUE,
pSysMem,
DX8Flags);
if (hr != DD_OK)
{
LEAVE_WIN16LOCK();
goto CreateErrorCleanup;
}
// If we let DDraw decide between local vidmem / AGP, then we need
// to figure out which one it chose.
if (((LPDDRAWI_DDRAWSURFACE_INT)lpDDSurface)->lpLcl->ddsCaps.dwCaps & DDSCAPS_NONLOCALVIDMEM)
{
pCreateSurface->Pool = D3DPOOL_NONLOCALVIDMEM;
for (i = 0; i < dwNumToCreate; i++)
{
pSurf = (DDSURFACE*) pCreateSurface->pSList[i].hKernelHandle;
pSurf->Pool = D3DPOOL_NONLOCALVIDMEM;
}
}
// Everything has worked
//Find the pointer to the attached heavyweight surface for
//each face, mip level, back buffer etc.
switch(pCreateSurface->Type)
{
case D3DRTYPE_VERTEXBUFFER :
case D3DRTYPE_INDEXBUFFER :
case D3DRTYPE_COMMANDBUFFER :
//these types have no attachments
DDASSERT(0 == ( (LPDDRAWI_DDRAWSURFACE_INT)lpDDSurface)->lpLcl->lpAttachList );
//but we need to fall through and set the pHeavy for the first one.
case D3DRTYPE_SURFACE :
case D3DRTYPE_IMAGESURFACE :
case D3DRTYPE_VOLUME :
case D3DRTYPE_TEXTURE :
case D3DRTYPE_VOLUMETEXTURE :
{
LPDDRAWI_DDRAWSURFACE_INT lpTemp;
LPDDRAWI_DDRAWSURFACE_INT lpTemp1;
lpTemp = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
//these types are allocated in a linear list of attachments
for (i = 0; i < dwNumToCreate; i++)
{
pSurf = (DDSURFACE*) pCreateSurface->pSList[i].hKernelHandle;
DDASSERT(!(pSurf->dwFlags & DDSURFACE_DUMMY)); //cuz not DX6 driver
if (pSurf->dwFlags & DDSURFACE_LIGHTWEIGHT)
{
ExtractLightweightInfo (pSurf, lpTemp);
}
else
{
pSurf->Surface.pHeavy = lpTemp;
}
lpTemp1 = lpTemp;
if (lpTemp->lpLcl->lpAttachList)
lpTemp = lpTemp->lpLcl->lpAttachList->lpIAttached;
pSurf->iSlicePitch = lpTemp1->lpLcl->lpGbl->lSlicePitch;
lpTemp1->lpLcl->lpGbl->lSlicePitch = 0;
if (pSurf->dwFlags & DDSURFACE_LIGHTWEIGHT)
{
if (lpTemp1->lpLcl->lpAttachList != NULL)
{
MemFree(lpTemp1->lpLcl->lpAttachList);
}
if (lpTemp1->lpLcl->lpAttachListFrom != NULL)
{
MemFree(lpTemp1->lpLcl->lpAttachListFrom);
}
DiscardHeavyweightMemory(lpTemp1);
}
}
}
break;
case D3DRTYPE_CUBETEXTURE :
//cubes are the hard buggers.
{
int face;
DWORD cLevels = dwNumToCreate/6;
for(face=0; face<6; face++)
{
LPDDRAWI_DDRAWSURFACE_INT lpTemp;
lpTemp = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
//point lpTemp to the next top-level face (which will be
//attached to the face returned by create-surface)
//(we are already pointing thereat if it's face 0)
if (face)
{
LPATTACHLIST pal;
pal = lpTemp->lpLcl->lpAttachList;
do
{
lpTemp = pal->lpIAttached;
pal = pal->lpLink;
}
while(0 == (lpTemp->lpLcl->lpSurfMore->ddsCapsEx.dwCaps2 & dwOrderedFaces[face]));
}
//for each face, we run down the attachment list
//which are allocated in a linear list of attachments
for (i = 0; i < cLevels; i++)
{
pSurf = (DDSURFACE*) pCreateSurface->pSList[face*cLevels+i].hKernelHandle;
DDASSERT(!(pSurf->dwFlags & DDSURFACE_DUMMY)); //cuz not DX6 driver
pSurf->iSlicePitch = lpTemp->lpLcl->lpGbl->lSlicePitch;
lpTemp->lpLcl->lpGbl->lSlicePitch = 0;
if (pSurf->dwFlags & DDSURFACE_LIGHTWEIGHT)
{
ExtractLightweightInfo (pSurf, lpTemp);
}
else
{
pSurf->Surface.pHeavy = lpTemp;
}
if ((face == 0) && (i == 0) && (cLevels > 1))
{
// Special hack for finding mip-levels
// of first face; the mip-levels for the pos-x
// face are actually near the the end of the
// list (interposed by the top-levels of the
// other 5 faces)
int j;
LPATTACHLIST pal = lpTemp->lpLcl->lpAttachList;
for (j = 0; j < 5; j++)
{
pal = pal->lpLink;
}
lpTemp = pal->lpIAttached;
// Check we found what we were looking for
DDASSERT(lpTemp->lpLcl->lpSurfMore->ddsCapsEx.dwCaps2 & dwOrderedFaces[face]);
}
else if (lpTemp->lpLcl->lpAttachList)
{
// Normal case; i.e. just go to the surface we
// are directly attached to
lpTemp = lpTemp->lpLcl->lpAttachList->lpIAttached;
}
}
}
// If it's a lightweight surface, now we need to free
// all of the heavyweight memory
if (pSurf->dwFlags & DDSURFACE_LIGHTWEIGHT)
{
LPDDRAWI_DDRAWSURFACE_INT lpTemp;
LPATTACHLIST pal;
LPATTACHLIST pNextPal;
LPATTACHLIST pFaceList;
LPATTACHLIST pTemp;
lpTemp = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
pal = lpTemp->lpLcl->lpAttachList;
DiscardHeavyweightMemory(lpTemp);
while (pal != NULL)
{
pNextPal = pal->lpLink;
pFaceList = pal;
while (pFaceList != NULL)
{
if (pFaceList->lpAttached->lpAttachListFrom)
{
MemFree (pFaceList->lpAttached->lpAttachListFrom);
}
pTemp = pFaceList->lpAttached->lpAttachList;
DiscardHeavyweightMemory(pFaceList->lpIAttached);
MemFree(pFaceList);
pFaceList = pTemp;
}
pal = pNextPal;
}
}
}
break;
default:
DDASSERT(0); //unexpected type
break;
}
for (i = 0; i < dwNumToCreate; i++)
{
DWORD j;
pSurf = (DDSURFACE*) pCreateSurface->pSList[i].hKernelHandle;
if (i == 0)
{
pSurf->dwFlags |= DDSURFACE_ROOT;
}
if (pSurf->dwFlags & DDSURFACE_HEAVYWEIGHT)
{
pSurf->Pitch = pSurf->Surface.pHeavy->lpLcl->lpGbl->lPitch;
if (!(pSurf->dwFlags & DDSURFACE_DUMMY))
{
if (i == 0)
{
if (DDSCAPS_PRIMARYSURFACE &
pSurf->Surface.pHeavy->lpLcl->ddsCaps.dwCaps)
{
if (!(DDRAWILCL_HASEXCLUSIVEMODE & pdrv_int->lpLcl->dwLocalFlags))
{
LPDIRECTDRAWCLIPPER pcClipper;
if (SUCCEEDED(DD_CreateClipper((LPDIRECTDRAW) pdrv_int,
0, &pcClipper, NULL)))
{
if (pdrv_int->lpLcl->hWnd)
DD_Clipper_SetHWnd(pcClipper, 0, (HWND) pdrv_int->lpLcl->hWnd);
DD_Surface_SetClipper(lpDDSurface, pcClipper);
DPF(10,"Setting Clipper=%08lx with hWnd=%08lx to Primary"
" Surface", pcClipper, pdrv_int->lpLcl->hWnd);
DD_Clipper_Release(pcClipper);
}
}
}
}
}
pCreateSurface->pSList[i].hKernelHandle = (HANDLE) pSurf;
}
// If this is a DX6+ driver, the above CreateSurface call would
// have created the ExSurface and assigned a driver handle value.
// If it's a DX6 driver, however, we need to create the texture
// handle ourselves.
if (pDevice->DriverLevel > 6)
{
if (pSurf->dwFlags & DDSURFACE_HEAVYWEIGHT)
{
pSurf->dwCookie = pSurf->Surface.pHeavy->lpLcl->lpSurfMore->dwSurfaceHandle;
}
if (pSurf->dwCookie &&
bLost &&
(pSurf->dwFlags & DDSURFACE_ROOT))
{
// We've created the surface, but we can't create the
// surface Ex handle yet, so we will defer that creation until later.
pSurf->dwFlags |= DDSURFACE_DEFERCREATEEX;
}
}
else if ((pSurf->dwFlags & DDSURFACE_ROOT) &&
(pSurf->Type == D3DRTYPE_TEXTURE))
{
// Don't create a texture handle if the surface is in sysmem
// and the device doesn't texture from sysmem
if ((pCreateSurface->Pool != D3DPOOL_SYSTEMMEM) ||
pDevice->bCanTextureSysmem)
{
D3DHAL_TEXTURECREATEDATA data;
DWORD ret;
if (pDevice->pDD->lpLcl->lpGbl->lpD3DHALCallbacks->TextureCreate == NULL)
{
hr = DDERR_UNSUPPORTED;
LEAVE_WIN16LOCK();
goto CreateErrorCleanup;
}
if (bLost)
{
// We cannot create the texture handle at this time,
// so we will do it later.
pSurf->dwFlags |= DDSURFACE_DEFERCREATETEXHANDLE;
pDevice->pContext->dwFlags |= DDCONTEXT_DEFEREDTEXTUREHANDLES;
}
else
{
// If it's a palettized texture, we need to associate a
// palette before calling TextureCreate or else some
// drivers (Rage128) will fault.
if ((pCreateSurface->Format == D3DFMT_P8) ||
(pCreateSurface->Format == D3DFMT_A8P8))
{
if (pDevice->pDefaultPalette == NULL)
{
{
PALETTEENTRY ColorTable[256];
int i;
for (i = 0; i < 256; i++)
{
ColorTable[i].peRed = (UCHAR) i;
ColorTable[i].peGreen = (UCHAR) i;
ColorTable[i].peBlue = (UCHAR) i;
}
DD_CreatePalette ((LPDIRECTDRAW) pDevice->pDD,
DDPCAPS_8BIT,
ColorTable,
&pDevice->pDefaultPalette,
NULL);
}
if (pDevice->pDefaultPalette == NULL)
{
DPF_ERR("Unable to create default palette");
LEAVE_WIN16LOCK();
hr = DDERR_OUTOFMEMORY;
goto CreateErrorCleanup;
}
}
hr = DD_Surface_SetPalette(lpDDSurface,
pDevice->pDefaultPalette);
if (hr != DD_OK)
{
DPF_ERR("Unable to set default palette");
LEAVE_WIN16LOCK();
goto CreateErrorCleanup;
}
}
memset(&data, 0, sizeof(D3DHAL_TEXTURECREATEDATA));
data.dwhContext = pDevice->pContext->Context;
data.lpDDS = lpDDSurface;
CALL_D3DHAL_TAKEBUSY_NOWIN16(ret,
pDevice,
pDevice->pDD->lpLcl->lpGbl->lpD3DHALCallbacks->TextureCreate,
&data);
if (ret != DDHAL_DRIVER_HANDLED || data.ddrval != DD_OK)
{
DPF_ERR("HAL failed to handle TextureCreate");
LEAVE_WIN16LOCK();
hr = data.ddrval;
goto CreateErrorCleanup;
}
pSurf->dwCookie = data.dwHandle;
pSurf->dwFlags |= DDSURFACE_DX6HANDLE;
}
}
}
}
}
LEAVE_WIN16LOCK();
}
// Now insert this into our linked list
// If re-using, then we are already on the list so don't do anything
if (!pCreateSurface->bReUse)
{
for (i = 0; i < dwNumToCreate; i++)
{
((PDDSURFACE)(pCreateSurface->pSList[i].hKernelHandle))->pNext =
pDevice->pSurfList;
((PDDSURFACE)(pCreateSurface->pSList[i].hKernelHandle))->pPrevious =
NULL;
if (pDevice->pSurfList != NULL)
{
pDevice->pSurfList->pPrevious = (PDDSURFACE)(pCreateSurface->pSList[i].hKernelHandle);
}
pDevice->pSurfList = (PDDSURFACE)(pCreateSurface->pSList[i].hKernelHandle);
}
}
LEAVE_DDRAW();
return DD_OK;
CreateErrorCleanup:
for (i = 0; i < pCreateSurface->dwSCnt; i++)
{
pSurf = (PDDSURFACE)pCreateSurface->pSList[i].hKernelHandle;
if (pSurf != NULL)
{
FreeSurfaceObject(pSurf, TRUE);
// If we are reusing, then we need to keep the pSurf around
// for a retry
if (!pCreateSurface->bReUse)
{
MemFree(pSurf);
}
}
pCreateSurface->pSList[i].hKernelHandle = NULL;
}
LEAVE_DDRAW();
return MapLegacyResult(hr);
}
DWORD APIENTRY DdDestroySurface( PD3D8_DESTROYSURFACEDATA pDestroySurface )
{
DWORD i;
PDDSURFACE pSurf = (PDDSURFACE) pDestroySurface->hSurface;
PDDDEVICEHANDLE pDevice = (PDDDEVICEHANDLE) pDestroySurface->hDD;
PDEFERREDCREATE pDefCreate = pDevice->pDeferList;
ENTER_DDRAW();
FreeSurfaceObject(pSurf, TRUE);
if (pSurf != NULL)
{
// Free fpVidMem if we allocated it
if (pSurf->dwFlags & DDSURFACE_SYSMEMALLOCATED)
{
MemFree (pSurf->fpVidMem);
}
// Remove the surface from the linked list
if (pDevice->pSurfList == pSurf)
{
pDevice->pSurfList = pSurf->pNext;
if (pSurf->pNext != NULL)
{
pSurf->pNext->pPrevious = NULL;
}
}
else
{
if (pSurf->pNext != NULL)
{
pSurf->pNext->pPrevious = pSurf->pPrevious;
}
pSurf->pPrevious->pNext = pSurf->pNext;
}
MemFree(pSurf);
}
// We look in the defer list to see if any referenced surface
// is being destroyed. If this is the case, then we need to
// update the defer list and mark the surfaces as freed so
// that we don't try and resurrect destroyed surfaces. Although
// this appears slow, it is not too bad because a deferred list
// will be present only if a mode switch happened. In this case,
// it doesn't hurt if things are a little slow.
while (pDefCreate != NULL)
{
for (i = 0; i < pDefCreate->CreateData.dwSCnt; i++)
{
if (pSurf == (PDDSURFACE) pDefCreate->CreateData.pSList[i].hKernelHandle)
{
pDefCreate->CreateData.pSList[i].hKernelHandle = 0;
break;
}
}
pDefCreate = pDefCreate->pNext;
}
LEAVE_DDRAW();
return DD_OK;
}
DWORD APIENTRY DdGetScanLine( PD3D8_GETSCANLINEDATA pGetScanLine )
{
PDDDEVICEHANDLE pDevice = (PDDDEVICEHANDLE) pGetScanLine->hDD;
DWORD dwRet = DDHAL_DRIVER_HANDLED;
ENTER_BOTH();
if (CheckForDeviceLost(pDevice))
{
static int LostScanLine;
// When lost, we want to mix up the return values in case somebody
// calling us is waiting for these values to change
pGetScanLine->ddRVal = DD_OK;
if (LostScanLine == 0)
{
pGetScanLine->dwScanLine = 0;
pGetScanLine->bInVerticalBlank = TRUE;
}
else
{
pGetScanLine->dwScanLine = LostScanLine;
pGetScanLine->bInVerticalBlank = FALSE;
}
if ((LostScanLine += 10) > 100)
{
LostScanLine = 0;
}
}
else
{
LPDDHAL_GETSCANLINE gslhalfn;
LPDDHAL_GETSCANLINE gslfn;
gslfn = pDevice->pDD->lpLcl->lpDDCB->HALDD.GetScanLine;
gslhalfn = pDevice->pDD->lpLcl->lpDDCB->cbDDCallbacks.GetScanLine;
if( gslhalfn != NULL )
{
DDHAL_GETSCANLINEDATA gsld;
gsld.GetScanLine = gslhalfn;
gsld.lpDD = pDevice->pDD->lpLcl->lpGbl;
DOHALCALL( GetScanLine, gslfn, gsld, dwRet, FALSE );
if( dwRet == DDHAL_DRIVER_HANDLED )
{
pGetScanLine->dwScanLine = gsld.dwScanLine;
if (gsld.ddRVal == DDERR_VERTICALBLANKINPROGRESS)
{
gsld.ddRVal = DD_OK;
pGetScanLine->bInVerticalBlank = TRUE;
}
else
{
pGetScanLine->bInVerticalBlank = FALSE;
}
pGetScanLine->ddRVal = MapLegacyResult(gsld.ddRVal);
}
}
else
{
dwRet = DDHAL_DRIVER_NOTHANDLED;
}
}
LEAVE_BOTH();
return dwRet;
}
DWORD APIENTRY DdSetExclusiveMode( PD3D8_SETEXCLUSIVEMODEDATA pSetExclusiveMode )
{
DPF_ERR("DdSetExclusiveMode");
#if 0
LPDDRAWI_DIRECTDRAW_LCL lpDX7;
// Tell DDraw that we've grabbed exclusive mode
ENTER_DDRAW();
lpDX7 = ((LPDDRAWI_DIRECTDRAW_INT)(pSetExclusiveMode->lpDD->hDD))->lpLcl;
if( pSetExclusiveMode->dwEnterExcl )
{
lpDX7->dwLocalFlags |= DDRAWILCL_SETCOOPCALLED | DDRAWILCL_ISFULLSCREEN;
lpDX7->lpGbl->lpExclusiveOwner = lpDX7;
lpDX7->lpGbl->dwFlags |= DDRAWI_FULLSCREEN;
}
else
{
lpDX7->dwLocalFlags &= ~(DDRAWILCL_SETCOOPCALLED | DDRAWILCL_ISFULLSCREEN);
lpDX7->lpGbl->lpExclusiveOwner = NULL;
lpDX7->lpGbl->dwFlags &= ~DDRAWI_FULLSCREEN;
}
LEAVE_DDRAW();
#endif
pSetExclusiveMode->ddRVal = DD_OK;
return DDHAL_DRIVER_HANDLED;
}
DWORD APIENTRY DdFlipToGDISurface( PD3D8_FLIPTOGDISURFACEDATA pFlipToGDISurface )
{
PDDDEVICEHANDLE pDevice = (PDDDEVICEHANDLE) pFlipToGDISurface->hDD;
LPDDRAWI_DIRECTDRAW_INT lpDD = pDevice->pDD;
pFlipToGDISurface->ddRVal = MapLegacyResult(DD_FlipToGDISurface((LPDIRECTDRAW)lpDD));
return DDHAL_DRIVER_HANDLED;
}
DWORD APIENTRY DdSetColorkey( PD3D8_SETCOLORKEYDATA pSetColorkey)
{
PDDDEVICEHANDLE pDevice = (PDDDEVICEHANDLE) pSetColorkey->hDD;
PDDSURFACE pSurf = (PDDSURFACE) pSetColorkey->hSurface;
ENTER_BOTH();
pSetColorkey->ddRVal = DD_OK;
if (CheckForDeviceLost(pSetColorkey->hDD))
{
LEAVE_BOTH();
return DDHAL_DRIVER_HANDLED;
}
if (pSurf->Surface.pHeavy != NULL)
{
DDCOLORKEY DDColorKey;
// Since this will only be called with DX6 drivers, we know that
// it will only be heavyweight surfaces and we can use the legacy
// entry point.
DDColorKey.dwColorSpaceLowValue = pSetColorkey->ColorValue;
pSetColorkey->ddRVal = MapLegacyResult(DD_Surface_SetColorKey((LPDIRECTDRAWSURFACE)pSurf->Surface.pHeavy,
DDCKEY_SRCBLT,
&DDColorKey));
}
LEAVE_BOTH();
return DDHAL_DRIVER_HANDLED;
}
DWORD APIENTRY DdGetAvailDriverMemory( PD3D8_GETAVAILDRIVERMEMORYDATA pGetAvailDriverMemory )
{
DWORD dwTotal;
DWORD dwFree;
DDSCAPS ddscaps;
LPDDRAWI_DIRECTDRAW_INT pdrv_int = ((PDDDEVICEHANDLE)pGetAvailDriverMemory->hDD)->pDD;
ddscaps.dwCaps = DDSCAPS_TEXTURE;
pGetAvailDriverMemory->ddRVal = MapLegacyResult(DD_GetAvailableVidMem( (LPDIRECTDRAW)pdrv_int, &ddscaps, &dwTotal, &dwFree ));
pGetAvailDriverMemory->dwFree = dwFree;
return DDHAL_DRIVER_HANDLED;
}
HRESULT CalcDDSurfInfo( PDDCONTEXT pCtx, LPDDRAWI_DDRAWSURFACE_LCL pSLcl,
LPDDRAWI_DDRAWSURFACE_LCL pZLcl )
{
HRESULT ddrval;
DWORD dwWidth, dwHeight;
unsigned long m;
int s;
LPDDPIXELFORMAT pSPixFmt = NULL;
LPDDPIXELFORMAT pZPixFmt = NULL;
if( pSLcl == NULL ) return S_OK;
// Get info from the surface
dwWidth = pSLcl->lpGbl->wWidth;
dwHeight = pSLcl->lpGbl->wHeight;
GET_PIXEL_FORMAT( pSLcl, pSLcl->lpGbl, pSPixFmt );
if( ( pSPixFmt->dwFlags & ( DDPF_PALETTEINDEXED4 |
DDPF_PALETTEINDEXED8 ) ) == 0 )
{
// palettized pixfmts will not have valid RGB Bitmasks, so avoid
// computing this for them
pCtx->red_mask = pSPixFmt->dwRBitMask;
pCtx->green_mask = pSPixFmt->dwGBitMask;
pCtx->blue_mask = pSPixFmt->dwBBitMask;
if( (pCtx->red_mask == 0x0) || (pCtx->green_mask == 0x0) ||
(pCtx->blue_mask == 0x0) )
{
D3D_ERR("All the color masks in the Render target's pixel-format "
"must be non-zero");
return DDERR_INVALIDPIXELFORMAT;
}
// these are used by Clear
for( s = 0, m = pCtx->red_mask; !(m & 1); s++, m >>= 1 );
pCtx->red_shift = s;
pCtx->red_scale = 255 / (pCtx->red_mask >> s);
for( s = 0, m = pCtx->green_mask; !(m & 1); s++, m >>= 1 );
pCtx->green_shift = s;
pCtx->green_scale = 255 / (pCtx->green_mask >> s);
for( s = 0, m = pCtx->blue_mask; !(m & 1); s++, m >>= 1 );
pCtx->blue_shift = s;
pCtx->blue_scale = 255 / (pCtx->blue_mask >> s);
if( (pCtx->red_scale==0) || (pCtx->green_scale==0) ||
(pCtx->blue_scale==0) )
return DDERR_INVALIDPIXELFORMAT;
pCtx->bDDSTargetIsPalettized=FALSE;
}
else
{
pCtx->bDDSTargetIsPalettized=TRUE;
}
if( pZLcl )
{
// Get info from the surface
GET_PIXEL_FORMAT( pZLcl, pZLcl->lpGbl, pZPixFmt );
if( pZPixFmt->dwZBitMask!=0x0)
{
for(s = 0, m = pZPixFmt->dwZBitMask; !(m & 0x1); s++, m >>= 1);
pCtx->zmask_shift = s;
}
else
{
// if ZBitMask isn't being set, then Clear2 will never be used,
// so zbuf_shift/stencil_shift wont be needed anyway
pCtx->zmask_shift=0;
}
if( pZPixFmt->dwStencilBitMask != 0x0 )
{
for(s = 0, m = pZPixFmt->dwStencilBitMask; !(m & 0x1);
s++, m >>= 1) ;
pCtx->stencilmask_shift = s;
}
else
{
pCtx->stencilmask_shift=0;
}
}
return S_OK;
}
DWORD WINAPI D3dContextCreate(PD3D8_CONTEXTCREATEDATA pCreateContext)
{
D3DHAL_CONTEXTCREATEDATA data;
DWORD ret;
HRESULT hr = S_OK;
PDDDEVICEHANDLE pDevice = (PDDDEVICEHANDLE) pCreateContext->hDD;
LPDDRAWI_DIRECTDRAW_INT lpDD = pDevice->pDD;
PDDSURFACE lpDDSTarget = (PDDSURFACE)pCreateContext->hSurface;
PDDSURFACE lpDDSZBuffer = (PDDSURFACE)pCreateContext->hDDSZ;
PDDCONTEXT pContext;
ULONG cjBuffer = 0;
// Do the allocation first, since if it fails we don't have to do any real cleanup
ENTER_BOTH();
pDevice->pContext = NULL;
pContext = (PDDCONTEXT) MemAlloc(sizeof(DDCONTEXT));
if (pContext == NULL)
{
pCreateContext->ddrval = DDERR_OUTOFMEMORY;
LEAVE_BOTH();
return DDHAL_DRIVER_HANDLED;
}
// Now allocate the memory for the DPBuffer.
pContext->pDPBuffer = NULL;
cjBuffer = pCreateContext->cjBuffer;
if( cjBuffer == 0)
{
cjBuffer = DEF_PRIM_BUFFER_SIZE;
}
else if (cjBuffer < MIN_PRIM_BUFFER_SIZE ||
cjBuffer > MAX_PRIM_BUFFER_SIZE)
{
D3D_ERR("Illegal buffer size");
pCreateContext->ddrval = D3DERR_DRIVERINTERNALERROR;
MemFree( pContext );
LEAVE_BOTH();
return DDHAL_DRIVER_HANDLED;
}
pContext->pDPBuffer = (LPVOID)MemAlloc( cjBuffer );
if( pContext->pDPBuffer == NULL )
{
pCreateContext->ddrval = DDERR_OUTOFMEMORY;
MemFree( pContext );
LEAVE_BOTH();
return DDHAL_DRIVER_HANDLED;
}
pCreateContext->pvBuffer = (LPVOID)(((DWORD)pContext->pDPBuffer+31)&(~31));
pCreateContext->cjBuffer = cjBuffer;
// We need to check for a lost device before mucking around with the surfaces
if (CheckForDeviceLost(pDevice))
{
pContext->Context = 0;
pContext->pDevice = pDevice;
pDevice->pContext = pContext;
pCreateContext->dwhContext = (ULONG_PTR) pContext;
// Remember data required to create the context later
pContext->dwFlags = DDCONTEXT_DEFER;
pContext->dwTempContext = pCreateContext->dwhContext;
pContext->dwPID = pCreateContext->dwPID;
pContext->ddrval = pCreateContext->ddrval;
pCreateContext->ddrval = DD_OK;
LEAVE_BOTH();
return DDHAL_DRIVER_HANDLED;
}
// Calculate the surface info for Clear emulation if needed
hr = CalcDDSurfInfo( pContext,
(lpDDSTarget) ? lpDDSTarget->Surface.pHeavy->lpLcl
: NULL,
(lpDDSZBuffer) ? lpDDSZBuffer->Surface.pHeavy->lpLcl
: NULL );
if( FAILED( hr ) )
{
pCreateContext->ddrval = MapLegacyResult(hr);
MemFree(pContext->pDPBuffer);
pCreateContext->pvBuffer = NULL;
pCreateContext->cjBuffer = 0;
MemFree(pContext);
LEAVE_BOTH();
return DDHAL_DRIVER_HANDLED;
}
memset(&data, 0, sizeof(D3DHAL_CONTEXTCREATEDATA));
pDevice->pContext = NULL;
if (pDevice->DriverLevel >= 7)
{
if (lpDD)
data.lpDDLcl = lpDD->lpLcl;
else
data.lpDDLcl = NULL;
if (lpDDSTarget)
data.lpDDSLcl = lpDDSTarget->Surface.pHeavy->lpLcl;
else
data.lpDDSLcl = NULL;
if (lpDDSZBuffer)
data.lpDDSZLcl = lpDDSZBuffer->Surface.pHeavy->lpLcl;
else
data.lpDDSZLcl = NULL;
}
else
{
if (lpDD)
data.lpDDGbl = lpDD->lpLcl->lpGbl;
else
data.lpDDLcl = NULL;
if (lpDDSTarget)
data.lpDDS = (LPDIRECTDRAWSURFACE)lpDDSTarget->Surface.pHeavy;
else
data.lpDDS = NULL;
if (lpDDSZBuffer)
data.lpDDSZ = (LPDIRECTDRAWSURFACE)lpDDSZBuffer->Surface.pHeavy;
else
data.lpDDSZ = NULL;
}
// Hack Alert!! dwhContext is used to inform the driver which version
// of the D3D interface is calling it.
data.dwhContext = pCreateContext->dwhContext;
data.dwPID = pCreateContext->dwPID;
data.ddrval = pCreateContext->ddrval;
/* 0 for pre-DX5 devices.
* 1 for DX5 devices.
* 2 for DX6 devices.
* 3 for DX7 devices.
*/
CALL_D3DHAL_TAKEBUSY_NOWIN16(ret,
pDevice,
lpDD->lpLcl->lpGbl->lpD3DHALCallbacks->ContextCreate,
&data);
if (ret != DDHAL_DRIVER_HANDLED || data.ddrval != DD_OK)
{
D3D_ERR( "Driver did not handle ContextCreate" );
MemFree(pContext->pDPBuffer);
pCreateContext->pvBuffer = NULL;
pCreateContext->cjBuffer = 0;
MemFree(pContext);
pCreateContext->dwhContext = 0;
pCreateContext->ddrval = D3DERR_DRIVERINTERNALERROR;
}
else
{
pContext->Context = data.dwhContext;
pContext->pDevice = pDevice;
pDevice->pContext = pContext;
pCreateContext->dwhContext = (ULONG_PTR) pContext;
pCreateContext->ddrval = data.ddrval;
}
LEAVE_BOTH();
return DDHAL_DRIVER_HANDLED;
}
HRESULT WINAPI D3dContextDestroy(PD3D8_CONTEXTDESTROYDATA pDestroyContext)
{
PDDCONTEXT pContext = (PDDCONTEXT) pDestroyContext->dwhContext;
ENTER_BOTH();
CheckForDeviceLost(pContext->pDevice);
pDestroyContext->ddrval = DD_OK;
if (pContext->Context)
{
D3DHAL_CONTEXTDESTROYDATA data;
DWORD ret;
DDSURFACE* pSurf;
// If there are any DX6 texture handles created w/ this context,
// we should destroy them now.
pSurf = pContext->pDevice->pSurfList;
while (pSurf != NULL)
{
if ((pSurf->dwFlags & DDSURFACE_DX6HANDLE) &&
(pContext->pDevice->pDD->lpLcl->lpGbl->lpD3DHALCallbacks->TextureDestroy != NULL))
{
D3DHAL_TEXTUREDESTROYDATA data;
DWORD ret;
data.dwhContext = (ULONG_PTR) pContext->Context;
data.dwHandle = pSurf->dwCookie;
CALL_D3DHAL_TAKEBUSY_NOWIN16(ret,
pSurf->pDevice,
pSurf->pDevice->pDD->lpLcl->lpGbl->lpD3DHALCallbacks->TextureDestroy,
&data);
pSurf->dwFlags &= ~DDSURFACE_DX6HANDLE;
pSurf->dwCookie = 0;
}
pSurf = pSurf->pNext;
}
data.dwhContext = (ULONG_PTR) pContext->Context;
CALL_D3DHAL_TAKEBUSY_NOWIN16(ret,
pContext->pDevice,
pContext->pDevice->pDD->lpLcl->lpGbl->lpD3DHALCallbacks->ContextDestroy,
&data);
pDestroyContext->ddrval = MapLegacyResult(data.ddrval);
}
if( pContext->pDPBuffer ) MemFree( pContext->pDPBuffer );
pContext->pDevice->pContext = NULL;
MemFree(pContext);
LEAVE_BOTH();
return DDHAL_DRIVER_HANDLED;
}
void BltFillRects( PDDCONTEXT pCtx, PDDSURFACE pDDS, DWORD count,
LPD3DRECT rect, D3DCOLOR dwFillColor)
{
HRESULT ddrval;
DDBLTFX bltfx;
RECT tr;
DWORD i;
DWORD r, g, b;
// Fill with background color
memset(&bltfx, 0, sizeof(bltfx));
bltfx.dwSize = sizeof(bltfx);
// unlike clear callback, which just takes pure 32-bit ARGB word and forces the driver to scale it for
// the pixelformat, here we need to compute the exact fill word, depending on surface's R,G,B bitmasks
if( pCtx->bDDSTargetIsPalettized )
{
// Palettized render targets are not supported
DDASSERT( TRUE );
}
else
{
DDASSERT((pCtx->red_scale!=0)&&(pCtx->green_scale!=0)&&(pCtx->blue_scale!=0));
r = RGB_GETRED(dwFillColor) / pCtx->red_scale;
g = RGB_GETGREEN(dwFillColor) / pCtx->green_scale;
b = RGB_GETBLUE(dwFillColor) / pCtx->blue_scale;
bltfx.dwFillColor = (r << pCtx->red_shift) | (g << pCtx->green_shift) |
(b << pCtx->blue_shift);
}
for (i = 0; i < count; i++,rect++)
{
tr.left = rect->x1;
tr.right = rect->x2;
tr.top = rect->y1;
tr.bottom = rect->y2;
do
{
ddrval = DD_Surface_Blt( (LPDIRECTDRAWSURFACE)pDDS->Surface.pHeavy,
&tr, NULL, NULL, DDBLT_COLORFILL, &bltfx);
} while (ddrval == DDERR_WASSTILLDRAWING);
}
}
void BltFillZRects( PDDCONTEXT pCtx, PDDSURFACE pDDSZ, unsigned long Zpixel,
DWORD count, LPD3DRECT rect, DWORD dwWriteMask)
{
HRESULT ddrval;
DDBLTFX bltfx;
DWORD i;
RECT tr;
DWORD dwExtraFlags=0;
memset(&bltfx, 0, sizeof(DDBLTFX));
bltfx.dwSize = sizeof(DDBLTFX);
bltfx.dwFillDepth = Zpixel;
// hack to pass DepthBlt WriteMask through ddraw/ddhel to blitlib
if( dwWriteMask != 0 )
{
bltfx.dwZDestConstBitDepth = dwWriteMask;
dwExtraFlags = DDBLT_DEPTHFILLWRITEMASK;
}
for(i=0; i<count ; i++, rect++)
{
tr.left = rect->x1;
tr.right = rect->x2;
tr.top = rect->y1;
tr.bottom = rect->y2;
do
{
ddrval = DD_Surface_Blt(
(LPDIRECTDRAWSURFACE)pDDSZ->Surface.pHeavy,
&tr, NULL, NULL,
DDBLT_DEPTHFILL |
dwExtraFlags, &bltfx );
} while (ddrval == DDERR_WASSTILLDRAWING);
}
}
DWORD WINAPI D3dClear( PD3D8_CLEAR2DATA pData )
{
PDDCONTEXT pContext = (PDDCONTEXT) pData->dwhContext;
LPDDRAWI_DIRECTDRAW_GBL pGbl = NULL;
DWORD ret = DDHAL_DRIVER_HANDLED;
DWORD dwFlags = pData->dwFlags;
BOOL bDoRGBClear = ((dwFlags & D3DCLEAR_TARGET)!=0);
BOOL bDoZClear = ((dwFlags & D3DCLEAR_ZBUFFER)!=0);
BOOL bDoStencilClear = ((dwFlags & D3DCLEAR_STENCIL)!=0);
D3DVALUE dvZ = pData->dvFillDepth;
PDDSURFACE pZBuffer = NULL;
LPDDRAWI_DDRAWSURFACE_GBL pZGbl = NULL;
LPDDRAWI_DDRAWSURFACE_LCL pZLcl = NULL;
LPDDPIXELFORMAT pZPixFmt = NULL;
pData->ddrval = S_OK;
ENTER_BOTH();
if (CheckForDeviceLost(pContext->pDevice))
{
LEAVE_BOTH();
return DDHAL_DRIVER_HANDLED;
}
pGbl = pContext->pDevice->pDD->lpLcl->lpGbl;
if( pGbl->lpD3DHALCallbacks3->Clear2 )
{
D3DHAL_CLEAR2DATA Clear2Data;
memcpy( &Clear2Data, pData, sizeof( Clear2Data ) );
Clear2Data.dwhContext = pContext->Context;
Clear2Data.ddrval = S_OK;
CALL_D3DHAL_TAKEBUSY_NOWIN16( ret,
pContext->pDevice,
pGbl->lpD3DHALCallbacks3->Clear2,
(D3DHAL_CLEAR2DATA *)&Clear2Data);
LEAVE_BOTH();
pData->ddrval = MapLegacyResult(Clear2Data.ddrval);
return ret;
}
if( pGbl->lpD3DGlobalDriverData->hwCaps.dpcTriCaps.dwRasterCaps &
D3DPRASTERCAPS_ZBUFFERLESSHSR )
{
if( bDoStencilClear )
{
D3D_ERR( "Invalid flag D3DCLEAR_STENCIL: this ZBUFFERLESSHSR "
"device doesn't support Stencil Clears");
pData->ddrval = D3DERR_DRIVERINTERNALERROR;
LEAVE_BOTH();
return DDHAL_DRIVER_NOTHANDLED;
}
if( bDoZClear )
{
if( !(pGbl->lpD3DHALCallbacks2->Clear) || (dvZ != 1.0f) )
{
D3D_WARN(3,"Ignoring D3DCLEAR_ZBUFFER since this "
"ZBUFFERLESSHSR device doesn't even support Clear "
"or Z!=1");
dwFlags &= ~(D3DCLEAR_ZBUFFER);
}
}
}
if( pData->hDDSZ )
{
pZBuffer = (PDDSURFACE)pData->hDDSZ;
pZLcl = pZBuffer->Surface.pHeavy->lpLcl;
pZGbl = pZLcl->lpGbl;
pZPixFmt = &pZGbl->ddpfSurface;
}
if( pGbl->lpD3DHALCallbacks2->Clear )
{
D3DHAL_CLEARDATA ClearData;
if( bDoZClear || bDoStencilClear )
{
if( (pZPixFmt != NULL) && //PowerVR need no Zbuffer
(DDPF_STENCILBUFFER & pZPixFmt->dwFlags))
{
// if surface has stencil bits, must verify either Clear2
// callback exists or we're using SW rasterizers
// (which require the special WriteMask DDHEL blt)
// This case should not be hit since we check right at the
// driver initialization time if the driver doesnt report
// Clear2 yet it supports stencils
if( pZLcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY )
{
goto Emulateclear;
}
else
{
LEAVE_BOTH();
D3D_ERR( "Driver doesn't support StencilBuffer Clears");
pData->ddrval = D3DERR_DRIVERINTERNALERROR;
return DDHAL_DRIVER_NOTHANDLED;
}
}
// if Clear2 callback doesnt exist and it's a z-only surface and
// not doing zclear to non-max value then Clear2 is attempting to
// do no more than Clear could do, so it's safe to call Clear()
// instead of Clear2(), which will take advantage of older
// drivers that implement Clear but not Clear2
dwFlags &= ~D3DCLEAR_STENCIL; // Device cannot do stencil
}
if( bDoZClear && (dvZ != 1.0) )
{
ClearData.dwFlags = dwFlags & ~D3DCLEAR_ZBUFFER;
dwFlags = D3DCLEAR_ZBUFFER;
}
else
{
ClearData.dwFlags = dwFlags;
dwFlags = 0;
}
if (ClearData.dwFlags)
{
ClearData.dwhContext = pContext->Context;
// Here I will follow the ClearData.dwFillColor convention that
// color word is raw 32bit ARGB, unadjusted for surface bit depth
ClearData.dwFillColor = pData->dwFillColor;
// must clear to 0xffffffff because legacy drivers expect this
ClearData.dwFillDepth = 0xffffffff;
ClearData.lpRects = pData->lpRects;
ClearData.dwNumRects = pData->dwNumRects;
ClearData.ddrval = S_OK;
// if((err = CheckContextSurface(this)) != D3D_OK)
// {
// throw err;
// }
CALL_D3DHAL_TAKEBUSY_NOWIN16( ret,
pContext->pDevice,
pGbl->lpD3DHALCallbacks2->Clear,
(D3DHAL_CLEARDATA *)&ClearData);
pData->ddrval = MapLegacyResult(ClearData.ddrval);
LEAVE_BOTH();
return ret;
}
}
Emulateclear: // Fall back to Emulation using Blt
{
PDDSURFACE pTarget = (PDDSURFACE)pData->hDDS;
LPDDRAWI_DDRAWSURFACE_GBL pTargetGbl =
pTarget->Surface.pHeavy->lpLcl->lpGbl;
DWORD dwStencil = pData->dwFillStencil;
if(bDoRGBClear)
{
BltFillRects( pContext, (PDDSURFACE)pData->hDDS, pData->dwNumRects,
pData->lpRects, pData->dwFillColor );
//ok to not return possible errors from Blt?
}
if( (bDoZClear || bDoStencilClear) && NULL != pZPixFmt)
{
DWORD dwZbufferClearValue=0;
DWORD dwZbufferClearMask=0;
DDASSERT(pZPixFmt->dwZBufferBitDepth<=32);
DDASSERT(pZPixFmt->dwStencilBitDepth<32);
DDASSERT(pZPixFmt->dwZBitMask!=0x0);
DDASSERT((0xFFFFFFFF == (pZPixFmt->dwZBitMask |
pZPixFmt->dwStencilBitMask)) |
((DWORD)((1<<pZPixFmt->dwZBufferBitDepth)-1) ==
(pZPixFmt->dwZBitMask | pZPixFmt->dwStencilBitMask)));
DDASSERT(0==(pZPixFmt->dwZBitMask & pZPixFmt->dwStencilBitMask));
if(bDoZClear)
{
dwZbufferClearMask = pZPixFmt->dwZBitMask;
// special case the common cases
if( dvZ==1.0f )
{
dwZbufferClearValue = pZPixFmt->dwZBitMask;
}
else if( dvZ > 0.0f )
{
dwZbufferClearValue =
((DWORD)((dvZ*(pZPixFmt->dwZBitMask >>
pContext->zmask_shift)) + 0.5)) <<
pContext->zmask_shift;
}
}
if( bDoStencilClear )
{
DDASSERT(pZPixFmt->dwStencilBitMask!=0x0);
DDASSERT(pZPixFmt->dwFlags & DDPF_STENCILBUFFER);
dwZbufferClearMask |= pZPixFmt->dwStencilBitMask;
// special case the common case
if( dwStencil != 0 )
{
dwZbufferClearValue |= (dwStencil <<
pContext->stencilmask_shift) &
pZPixFmt->dwStencilBitMask;
}
}
if( dwZbufferClearMask == (pZPixFmt->dwStencilBitMask |
pZPixFmt->dwZBitMask) )
{
// do Stencil & Z Blt together, using regular DepthFill blt
// which will be faster than the writemask blt because its
// write-only, instead of read-modify-write
dwZbufferClearMask = 0;
}
BltFillZRects( pContext, (PDDSURFACE)pData->hDDSZ,
dwZbufferClearValue, pData->dwNumRects,
pData->lpRects, dwZbufferClearMask );
}
}
LEAVE_BOTH();
return ret;
}
DWORD WINAPI D3dSetRenderTarget( PD3D8_SETRENDERTARGETDATA pData )
{
PDDCONTEXT pContext = (PDDCONTEXT) pData->dwhContext;
LPDDRAWI_DIRECTDRAW_GBL pGbl = NULL;
DWORD ret = DDHAL_DRIVER_HANDLED;
ENTER_BOTH();
if (CheckForDeviceLost(pContext->pDevice))
{
LEAVE_BOTH();
pData->ddrval = DD_OK;
return DDHAL_DRIVER_HANDLED;
}
pGbl = pContext->pDevice->pDD->lpLcl->lpGbl;
if( pGbl->lpD3DHALCallbacks2->SetRenderTarget )
{
D3DHAL_SETRENDERTARGETDATA srtData;
// If creation of the render target was defered, create it now
if (pContext->dwFlags & DDCONTEXT_DEFER)
{
LPDDRAWI_DDRAWSURFACE_INT pTarget = NULL;
LPDDRAWI_DDRAWSURFACE_INT pZ = NULL;
HRESULT hr;
D3DHAL_CONTEXTCREATEDATA data;
DWORD ret;
if (pData->hDDS)
{
pTarget = ((PDDSURFACE)pData->hDDS)->Surface.pHeavy;
}
if (pData->hDDSZ)
{
pZ = ((PDDSURFACE)pData->hDDSZ)->Surface.pHeavy;
}
// Calculate the surface info for Clear emulation if needed
CalcDDSurfInfo(pContext,
(pTarget) ? pTarget->lpLcl : NULL,
(pZ) ? pZ->lpLcl : NULL);
memset(&data, 0, sizeof(D3DHAL_CONTEXTCREATEDATA));
if (pContext->pDevice->DriverLevel >= 7)
{
if (pContext->pDevice->pDD != NULL)
{
data.lpDDLcl = pContext->pDevice->pDD->lpLcl;
}
if (pTarget != NULL)
{
data.lpDDSLcl = pTarget->lpLcl;
}
else
{
data.lpDDSLcl = NULL;
}
if (pZ != NULL)
{
data.lpDDSZLcl = pZ->lpLcl;
}
else
{
data.lpDDSZLcl = NULL;
}
}
else
{
if (pContext->pDevice->pDD != NULL)
{
data.lpDDGbl = pContext->pDevice->pDD->lpLcl->lpGbl;
}
data.lpDDS = (LPDIRECTDRAWSURFACE)pTarget;
data.lpDDSZ = (LPDIRECTDRAWSURFACE) pZ;
}
// Hack Alert!! dwhContext is used to inform the driver which version
// of the D3D interface is calling it.
data.dwhContext = pContext->dwTempContext;
data.dwPID = pContext->dwPID;
data.ddrval = pContext->ddrval;
/* 0 for pre-DX5 devices.
* 1 for DX5 devices.
* 2 for DX6 devices.
* 3 for DX7 devices.
*/
CALL_D3DHAL_TAKEBUSY_NOWIN16(ret,
pContext->pDevice,
pContext->pDevice->pDD->lpLcl->lpGbl->lpD3DHALCallbacks->ContextCreate,
&data);
if (ret == DDHAL_DRIVER_HANDLED && data.ddrval == DD_OK)
{
pContext->Context = data.dwhContext;
}
pContext->dwFlags &= ~DDCONTEXT_DEFER;
}
pData->bNeedUpdate = FALSE;
memset( &srtData, 0, sizeof( srtData ) );
srtData.dwhContext = pContext->Context;
if( pData->hDDS )
srtData.lpDDS =
(LPDIRECTDRAWSURFACE)((PDDSURFACE)pData->hDDS)->Surface.pHeavy;
if( pData->hDDSZ )
srtData.lpDDSZ =
(LPDIRECTDRAWSURFACE)((PDDSURFACE)pData->hDDSZ)->Surface.pHeavy;
CALL_D3DHAL_TAKEBUSY_NOWIN16( ret,
pContext->pDevice,
pGbl->lpD3DHALCallbacks2->SetRenderTarget,
(D3DHAL_SETRENDERTARGETDATA *)&srtData );
pData->ddrval = MapLegacyResult(srtData.ddrval);
// If we need to create any defered texture handles, we will do so now
if (pContext->dwFlags & DDCONTEXT_DEFEREDTEXTUREHANDLES)
{
DDSURFACE* pSurf;
pContext->dwFlags &= ~ DDCONTEXT_DEFEREDTEXTUREHANDLES;
pSurf = pContext->pDevice->pSurfList;
while (pSurf != NULL)
{
if (pSurf->dwFlags & DDSURFACE_DEFERCREATETEXHANDLE)
{
D3DHAL_TEXTURECREATEDATA data;
DWORD ret;
memset(&data, 0, sizeof(D3DHAL_TEXTURECREATEDATA));
data.dwhContext = pContext->Context;
data.lpDDS = (LPDIRECTDRAWSURFACE) pSurf->Surface.pHeavy;
CALL_D3DHAL_TAKEBUSY_NOWIN16(ret,
pContext->pDevice,
pContext->pDevice->pDD->lpLcl->lpGbl->lpD3DHALCallbacks->TextureCreate,
&data);
pSurf->dwCookie = data.dwHandle;
pSurf->dwFlags |= DDSURFACE_DX6HANDLE;
pSurf->dwFlags &= ~DDSURFACE_DEFERCREATETEXHANDLE;
}
pSurf = pSurf->pNext;
}
}
LEAVE_BOTH();
return ret;
}
else
{
D3DHAL_CONTEXTCREATEDATA cdata;
D3DHAL_CONTEXTDESTROYDATA ddata;
DDSURFACE* pTemp;
// If we have allocated any texture handles, we need to free them now
pTemp = pContext->pDevice->pSurfList;
while (pTemp != NULL)
{
if ((pTemp->dwFlags & DDSURFACE_DX6HANDLE) &&
(pContext->pDevice->pDD->lpLcl->lpGbl->lpD3DHALCallbacks->TextureDestroy != NULL))
{
D3DHAL_TEXTUREDESTROYDATA data;
DWORD ret;
data.dwhContext = (ULONG_PTR) pContext->Context;
data.dwHandle = pTemp->dwCookie;
CALL_D3DHAL_TAKEBUSY_NOWIN16(ret,
pTemp->pDevice,
pTemp->pDevice->pDD->lpLcl->lpGbl->lpD3DHALCallbacks->TextureDestroy,
&data);
}
pTemp = pTemp->pNext;
}
pData->bNeedUpdate = TRUE;
memset( &ddata, 0, sizeof(D3DHAL_CONTEXTDESTROYDATA) );
// Destroy Old Context
ddata.dwhContext = pContext->Context;
if (pContext->Context != 0)
{
CALL_D3DHAL_TAKEBUSY_NOWIN16( ret,
pContext->pDevice,
pGbl->lpD3DHALCallbacks->ContextDestroy,
&ddata );
if (ret != DDHAL_DRIVER_HANDLED || ddata.ddrval != DD_OK)
{
D3D_ERR( "SRT emulation, ContextDestroy failed." );
LEAVE_BOTH();
pData->ddrval = MapLegacyResult(ddata.ddrval);
return ret;
}
}
pContext->dwFlags &= ~(DDCONTEXT_DEFER | DDCONTEXT_DEFEREDTEXTUREHANDLES);
// Create a new Context
memset( &cdata, 0, sizeof(D3DHAL_CONTEXTCREATEDATA) );
cdata.lpDDGbl = pGbl;
if( pData->hDDS )
cdata.lpDDS =
(LPDIRECTDRAWSURFACE)((PDDSURFACE)pData->hDDS)->Surface.pHeavy;;
if( pData->hDDSZ )
cdata.lpDDSZ =
(LPDIRECTDRAWSURFACE)((PDDSURFACE)pData->hDDSZ)->Surface.pHeavy;
// Hack Alert!! dwhContext is used to inform the driver which version
// of the D3D interface is calling it.
// We don't want DX6 drivers to know that we are DX8 because
// we found at least one driver that starts behaving differently when
// it sees anything other than 3. (the driver was TNT2 and it turned
// off multitexturing thinking that anything other than 3 means DX5
// or below)
cdata.dwhContext = 3;
DDASSERT(pContext->pDevice->DriverLevel < 7); // should never get here for DX7 or above drivers
cdata.dwPID = GetCurrentProcessId();
CALL_D3DHAL_TAKEBUSY_NOWIN16( ret,
pContext->pDevice,
pGbl->lpD3DHALCallbacks->ContextCreate,
&cdata );
if (ret != DDHAL_DRIVER_HANDLED || cdata.ddrval != DD_OK)
{
D3D_ERR( "SRT emulation, ContextCreate failed" );
LEAVE_BOTH();
pData->dwhContext = 0;
pData->ddrval = MapLegacyResult(cdata.ddrval);
return ret;
}
pContext->Context = cdata.dwhContext;
pData->ddrval = MapLegacyResult(cdata.ddrval);
// Now we need to re-create any texture handles that we destroyed
if (pData->ddrval == DD_OK)
{
pTemp = pContext->pDevice->pSurfList;
while (pTemp != NULL)
{
if ((pTemp->dwFlags & DDSURFACE_DX6HANDLE) ||
(pTemp->dwFlags & DDSURFACE_DEFERCREATETEXHANDLE))
{
D3DHAL_TEXTURECREATEDATA data;
DWORD ret;
memset(&data, 0, sizeof(D3DHAL_TEXTURECREATEDATA));
data.dwhContext = pContext->Context;
data.lpDDS = (LPDIRECTDRAWSURFACE) pTemp->Surface.pHeavy;
CALL_D3DHAL_TAKEBUSY_NOWIN16(ret,
pTemp->pDevice,
pTemp->pDevice->pDD->lpLcl->lpGbl->lpD3DHALCallbacks->TextureCreate,
&data);
pTemp->dwCookie = data.dwHandle;
pTemp->dwFlags |= DDSURFACE_DX6HANDLE;
pTemp->dwFlags &= ~DDSURFACE_DEFERCREATETEXHANDLE;
}
pTemp = pTemp->pNext;
}
}
}
LEAVE_BOTH();
return ret;
}
HRESULT WINAPI D3dContextDestroyAll(PD3D8_CONTEXTDESTROYALLDATA pDestroyAllContext)
{
return DDHAL_DRIVER_HANDLED;
}
HRESULT WINAPI D3dGetDriverState(PD3D8_GETDRIVERSTATEDATA pGetDriverState)
{
PDDCONTEXT pContext = (PDDCONTEXT) pGetDriverState->dwhContext;
DWORD dwRet = DDHAL_DRIVER_HANDLED;
ULONG_PTR pTemp;
pGetDriverState->ddRVal = D3DERR_DRIVERINTERNALERROR;
ENTER_BOTH();
if (!CheckForDeviceLost(pContext->pDevice))
{
pTemp = pGetDriverState->dwhContext;
pGetDriverState->dwhContext = (ULONG_PTR) pContext->Context;
CALL_D3DHAL_TAKEBUSY_NOWIN16(dwRet,
pContext->pDevice,
pContext->pDevice->pDD->lpLcl->lpGbl->lpDDCBtmp->HALDDMiscellaneous2.GetDriverState,
(LPDDHAL_GETDRIVERSTATEDATA)pGetDriverState);
pGetDriverState->dwhContext = pTemp;
pGetDriverState->ddRVal = MapLegacyResult(pGetDriverState->ddRVal);
}
LEAVE_BOTH();
return dwRet;
}
HRESULT WINAPI D3dValidateTextureStageState(PD3D8_VALIDATETEXTURESTAGESTATEDATA pValidate)
{
PDDCONTEXT pContext = (PDDCONTEXT) pValidate->dwhContext;
DWORD dwRet = DDHAL_DRIVER_HANDLED;
ULONG_PTR pTemp;
pValidate->ddrval = D3DERR_DEVICELOST;
pValidate->dwNumPasses = 0;
ENTER_BOTH();
if (!CheckForDeviceLost(pContext->pDevice))
{
pTemp = pValidate->dwhContext;
pValidate->dwhContext = (ULONG_PTR) pContext->Context;
CALL_D3DHAL_TAKEBUSY_NOWIN16(dwRet,
pContext->pDevice,
pContext->pDevice->pDD->lpLcl->lpGbl->lpD3DHALCallbacks3->ValidateTextureStageState,
(D3DHAL_VALIDATETEXTURESTAGESTATEDATA*) pValidate);
pValidate->dwhContext = pTemp;
}
LEAVE_BOTH();
return dwRet;
}
DWORD WINAPI D3dDrawPrimitives2(PD3D8_DRAWPRIMITIVES2DATA pdp2data)
{
D3DHAL_DRAWPRIMITIVES2DATA dp2data;
DWORD ret = 0;
PDDCONTEXT pContext = (PDDCONTEXT) pdp2data->dwhContext;
DDSURFACE* pSurfCommand;
LPDDRAWI_DDRAWSURFACE_INT pHeavyCommand;
DDSURFACE* pSurfVertex = NULL;
LPDDRAWI_DDRAWSURFACE_INT pHeavyVertex = NULL;
// Copy the data into our structure for easy access
memcpy (&dp2data, pdp2data, sizeof(dp2data));
// Start processing
ENTER_BOTH();
// Handle loss
if (CheckForDeviceLost(((PDDSURFACE)pdp2data->hDDCommands)->pDevice))
{
pdp2data->ddrval = DD_OK;
pdp2data->dwErrorOffset = 0;
// Need to set these values to their original
// state so that the FE doesn't get confused.
pdp2data->fpVidMem_CB = 0;
pdp2data->dwLinearSize_CB = 0;
pdp2data->fpVidMem_VB = 0;
pdp2data->dwLinearSize_VB = 0;
// May need to return a pointer here
if ((dp2data.dwFlags & D3DHALDP2_SWAPVERTEXBUFFER) &&
!(dp2data.dwFlags & D3DHALDP2_USERMEMVERTICES))
{
DDSURFACE* pVertex = (PDDSURFACE)pdp2data->hDDVertex;
if (pVertex->Pool == D3DPOOL_SYSTEMMEM)
{
if (pVertex->dwFlags & DDSURFACE_LIGHTWEIGHT)
{
pdp2data->fpVidMem_VB = pVertex->Surface.pLight->fpGblVidMem;
pdp2data->dwLinearSize_VB = pVertex->Surface.pLight->GblPitch;
}
else
{
pdp2data->fpVidMem_VB = pVertex->Surface.pHeavy->lpLcl->lpGbl->fpVidMem;
pdp2data->dwLinearSize_VB = pVertex->Surface.pHeavy->lpLcl->lpGbl->dwLinearSize;
}
}
else if (pVertex->dwFlags & DDSURFACE_HEAVYWEIGHT)
{
if ((pVertex->fpVidMem == NULL) ||
!(pVertex->dwFlags & DDSURFACE_SYSMEMALLOCATED))
{
pVertex->fpVidMem = (char*) MemAlloc(pVertex->Pitch);
if (pVertex->fpVidMem != NULL)
{
pVertex->dwFlags |= DDSURFACE_SYSMEMALLOCATED;
}
}
if (pVertex->dwFlags & DDSURFACE_SYSMEMALLOCATED)
{
pdp2data->fpVidMem_VB = (ULONG_PTR) pVertex->fpVidMem;
pdp2data->dwLinearSize_VB = pVertex->Pitch;
}
else
{
pdp2data->ddrval = DDERR_GENERIC;
}
}
}
LEAVE_BOTH();
return DDHAL_DRIVER_HANDLED;
}
pSurfCommand = (PDDSURFACE)pdp2data->hDDCommands;
pHeavyCommand = GetHeavyweightSurf(pSurfCommand);
if (pHeavyCommand != NULL)
{
dp2data.lpDDCommands = pHeavyCommand->lpLcl;
}
else
{
pdp2data->ddrval = DDERR_OUTOFMEMORY;
LEAVE_BOTH();
return DDHAL_DRIVER_HANDLED;
}
if (!(pdp2data->dwFlags & D3DHALDP2_USERMEMVERTICES))
{
pSurfVertex = (PDDSURFACE)pdp2data->hDDVertex;
pHeavyVertex = GetHeavyweightSurf(pSurfVertex);
dp2data.lpDDVertex = pHeavyVertex->lpLcl;
}
dp2data.dwhContext = ((PDDCONTEXT)dp2data.dwhContext)->Context;
if (((PDDSURFACE)pdp2data->hDDCommands)->pDevice->pDD->lpLcl->lpGbl->lpD3DHALCallbacks3->DrawPrimitives2)
{
CALL_D3DHAL_TAKEBUSY_NOWIN16(
ret,
((PDDSURFACE)pdp2data->hDDCommands)->pDevice,
((PDDSURFACE)pdp2data->hDDCommands)->pDevice->pDD->lpLcl->lpGbl->lpD3DHALCallbacks3->DrawPrimitives2,
&dp2data);
if ((ret == DDHAL_DRIVER_HANDLED) && (dp2data.ddrval != DD_OK)
&& (DDERR_WASSTILLDRAWING != dp2data.ddrval))
{
((PDDSURFACE)pdp2data->hDDCommands)->pDevice->bDP2Error = TRUE;
}
}
// If the call to the driver succeded, swap the buffers if needed and
// perform GetAliasVidmem
if (ret == DDHAL_DRIVER_HANDLED && (dp2data.ddrval == DD_OK))
{
pdp2data->fpVidMem_CB = 0;
pdp2data->dwLinearSize_CB = 0;
pdp2data->fpVidMem_VB = 0;
pdp2data->dwLinearSize_VB = 0;
if (dp2data.dwFlags & D3DHALDP2_SWAPCOMMANDBUFFER)
{
// CONSIDER: Implement VidMem command buffer
}
if ((dp2data.dwFlags & D3DHALDP2_SWAPVERTEXBUFFER) && !(dp2data.dwFlags & D3DHALDP2_USERMEMVERTICES))
{
FLATPTR paliasbits;
DWORD dwLinearSize = dp2data.lpDDVertex->lpGbl->dwLinearSize;
if (dp2data.dwFlags & D3DHALDP2_VIDMEMVERTEXBUF)
{
paliasbits = GetAliasedVidMem( dp2data.lpDDVertex->lpSurfMore->lpDD_lcl,
dp2data.lpDDVertex,
(FLATPTR) dp2data.lpDDVertex->lpGbl->fpVidMem );
if (paliasbits == 0)
{
D3D_ERR( "Could not get Aliased pointer for vid mem vertex buffer" );
// Since we can't use this pointer, set it's size to 0
// That way next time around we will try and allocate a new one
dwLinearSize = 0;
}
}
else
{
paliasbits = dp2data.lpDDVertex->lpGbl->fpVidMem;
}
pdp2data->fpVidMem_VB = paliasbits;
pdp2data->dwLinearSize_VB = dwLinearSize;
}
}
if ((pSurfCommand->dwFlags & DDSURFACE_LIGHTWEIGHT) &&
(pHeavyCommand != NULL))
{
UnmapLightweightSurface (pSurfCommand);
}
if ((pSurfVertex != NULL ) &&
(pSurfVertex->dwFlags & DDSURFACE_LIGHTWEIGHT) &&
(pHeavyVertex != NULL))
{
UnmapLightweightSurface (pSurfVertex);
}
pdp2data->ddrval = dp2data.ddrval;
pdp2data->dwErrorOffset = dp2data.dwErrorOffset;
LEAVE_BOTH();
// We don't map the errors to the new ones because the runtime still needs
// to deal with WASSTILLDRAWING, so it does the mapping instead of us.
return ret;
}
PALETTEINFO* GetPaletteInfo (PDDDEVICEHANDLE pDevice, DWORD PaletteID)
{
PALETTEINFO* pPaletteInfo;
HRESULT hr;
DWORD i;
// The palette IDs are app defined and can range from 0 - 65500. We don't
// want to always allocate a table with 65500 entries, and we don't want
// to walk a list on every palette call, so we will grow the table to the
// desired whenever we need to. This works well if we assume that most
// apps will start with low numbers and then work up.
if (PaletteID >= pDevice->NumPaletteHandleEntries)
{
// We need to grow the table
DWORD NewTableSize;
PALETTEINFO** pNewTable;
if (((DWORD)-1) - PaletteID <= EXTRA_PALETTE_PADDING)
{
NewTableSize = PaletteID + 1;
}
else
{
NewTableSize = PaletteID + EXTRA_PALETTE_PADDING + 1;
}
pNewTable = MemAlloc(NewTableSize * sizeof(PALETTEINFO*));
if (pNewTable == NULL)
{
return NULL;
}
if ((pDevice->pPaletteHandleTable) &&
(pDevice->NumPaletteHandleEntries > 0))
{
memcpy(pNewTable,
pDevice->pPaletteHandleTable,
pDevice->NumPaletteHandleEntries * sizeof(PALETTEINFO*));
MemFree(pDevice->pPaletteHandleTable);
}
pDevice->pPaletteHandleTable = pNewTable;
pDevice->NumPaletteHandleEntries = NewTableSize;
}
// If we already have info for this palette, we just return it now
if (pDevice->pPaletteHandleTable[PaletteID] != NULL)
{
return pDevice->pPaletteHandleTable[PaletteID];
}
// Otherwise, we allocate a structure and initialize it
pPaletteInfo = MemAlloc(sizeof(PALETTEINFO));
if (pPaletteInfo == NULL)
{
return NULL;
}
for (i = 0; i < 256; i++)
{
pPaletteInfo->ColorTable[i].peRed = (UCHAR) i;
pPaletteInfo->ColorTable[i].peGreen = (UCHAR) i;
pPaletteInfo->ColorTable[i].peBlue = (UCHAR) i;
pPaletteInfo->ColorTable[i].peFlags = (UCHAR) 0;
}
hr = DD_CreatePalette ((LPDIRECTDRAW) pDevice->pDD,
DDPCAPS_8BIT,
pPaletteInfo->ColorTable,
&pPaletteInfo->pDDPalette,
NULL);
if (hr != DD_OK)
{
MemFree(pPaletteInfo);
return NULL;
}
pDevice->pPaletteHandleTable[PaletteID] = pPaletteInfo;
return pPaletteInfo;
}
DWORD WINAPI DdSetPalette (PD3D8_SETPALETTEDATA pSetPalette)
{
PALETTEINFO* pPalette;
DDASSERT (((PDDDEVICEHANDLE)pSetPalette->hDD)->DriverLevel == 6);
ENTER_BOTH();
CheckForDeviceLost(pSetPalette->hDD);
pSetPalette->ddRVal = D3DERR_DRIVERINTERNALERROR;
pPalette = GetPaletteInfo (pSetPalette->hDD,
pSetPalette->Palette);
if (pPalette != NULL)
{
pSetPalette->ddRVal = DD_OK;
if ((((DDSURFACE*)pSetPalette->hSurface)->Surface.pHeavy != NULL) &&
(((DDSURFACE*)pSetPalette->hSurface)->Surface.pHeavy->lpLcl->lpDDPalette !=
(LPDDRAWI_DDRAWPALETTE_INT)pPalette->pDDPalette))
{
pSetPalette->ddRVal = MapLegacyResult(DD_Surface_SetPalette(
(LPDIRECTDRAWSURFACE)((DDSURFACE*)pSetPalette->hSurface)->Surface.pHeavy,
pPalette->pDDPalette));
}
}
LEAVE_BOTH();
return DDHAL_DRIVER_HANDLED;
}
DWORD WINAPI DdUpdatePalette (PD3D8_UPDATEPALETTEDATA pUpdatePalette)
{
PALETTEINFO* pPalette;
DDASSERT (((PDDDEVICEHANDLE)pUpdatePalette->hDD)->DriverLevel == 6);
ENTER_BOTH();
CheckForDeviceLost(pUpdatePalette->hDD);
pUpdatePalette->ddRVal = D3DERR_DRIVERINTERNALERROR;
pPalette = GetPaletteInfo (pUpdatePalette->hDD,
pUpdatePalette->Palette);
if (pPalette != NULL)
{
pUpdatePalette->ddRVal = MapLegacyResult(DD_Palette_SetEntries(
pPalette->pDDPalette,
0,
0,
256,
pUpdatePalette->ColorTable));
}
LEAVE_BOTH();
return DDHAL_DRIVER_HANDLED;
}
DWORD WINAPI D3dSceneCapture (PD3D8_SCENECAPTUREDATA pData)
{
PDDCONTEXT pContext = (PDDCONTEXT) pData->dwhContext;
LPDDRAWI_DIRECTDRAW_GBL pGbl = NULL;
DWORD ret = DDHAL_DRIVER_HANDLED;
pData->ddrval = S_OK;
ENTER_BOTH();
if (CheckForDeviceLost(pContext->pDevice))
{
LEAVE_BOTH();
return DDHAL_DRIVER_HANDLED;
}
pGbl = pContext->pDevice->pDD->lpLcl->lpGbl;
if( pGbl->lpD3DHALCallbacks->SceneCapture )
{
D3DHAL_SCENECAPTUREDATA SceneCaptureData;
memcpy( &SceneCaptureData, pData, sizeof( SceneCaptureData ) );
SceneCaptureData.dwhContext = pContext->Context;
SceneCaptureData.ddrval = S_OK;
CALL_D3DHAL_TAKEBUSY_NOWIN16( ret,
pContext->pDevice,
pGbl->lpD3DHALCallbacks->SceneCapture,
(D3DHAL_SCENECAPTUREDATA *)&SceneCaptureData);
LEAVE_BOTH();
pData->ddrval = MapLegacyResult(SceneCaptureData.ddrval);
return ret;
}
LEAVE_BOTH();
return DDHAL_DRIVER_HANDLED;
}
//
// D3D8CreateDirectDrawObject
//
// Creates a DirectDraw object in DDRAW.DLL. By mainting a full representation of
// this object in DDRAW.DLL, it will automatically update the HAL info after mode
// changes, etc.
VOID APIENTRY D3D8CreateDirectDrawObject( LPGUID lpGuid,
char *szDeviceName,
HANDLE* phDD,
D3DDEVTYPE Type,
HINSTANCE* phLibrary,
VOID* pInitFunction)
{
HRESULT hr;
LPDIRECTDRAW lpDD1;
PD3D8GetSWInfo pfnHookCreate;
DDDEVICEHANDLE* pDeviceHandle;
HKEY hKey = (HKEY) NULL;
ENTER_DDRAW();
*phDD = NULL;
*phLibrary = NULL;
pDeviceHandle = (PDDDEVICEHANDLE) MemAlloc(sizeof(DDDEVICEHANDLE));
if (pDeviceHandle == NULL)
{
LEAVE_DDRAW();
return;
}
lstrcpy(pDeviceHandle->szDeviceName, szDeviceName);
pDeviceHandle->PID = GetCurrentProcessId();
hr = InternalDirectDrawCreate (NULL, &lpDD1, NULL,
DDRAWILCL_DIRECTDRAW7 | DDRAWILCL_DIRECTDRAW8, szDeviceName);
if( DD_OK == hr )
{
// Make it point to the DX7 vtbl. Do this rather than a QI since
// a QI for a DX7 object has some extra overhead.
lpDD1->lpVtbl = (LPVOID) &dd7Callbacks;
pDeviceHandle->pDD = (HANDLE) (LPDDRAWI_DIRECTDRAW_INT)lpDD1;
pDeviceHandle->DeviceType = Type;
if (Type == D3DDEVTYPE_REF)
{
// Load the refrast and let them take things over
*phLibrary = LoadLibrary (D3D8_REFRASTNAME);
pDeviceHandle->pSwDD = SwDDICreateDirectDraw();
if (pDeviceHandle->pSwDD != NULL)
{
*phDD = (HANDLE*) pDeviceHandle;
}
else
{
lpDD1->lpVtbl->Release(lpDD1);
}
}
else if (Type == D3DDEVTYPE_SW)
{
pDeviceHandle->pSwDD = SwDDICreateDirectDraw();
if (pDeviceHandle->pSwDD != NULL)
{
*phDD = (HANDLE*) pDeviceHandle;
pDeviceHandle->pSwInitFunction = pInitFunction;
}
}
else
{
*phDD = (HANDLE*) pDeviceHandle;
}
}
if (*phDD == NULL)
{
MemFree(pDeviceHandle);
}
else
{
pDeviceHandle->pLink = pDeviceList;
pDeviceList = pDeviceHandle;
}
LEAVE_DDRAW();
// See if they want to explicitly enable/disable lightweight surfaces
if ((*phDD != NULL) && (!RegOpenKey(HKEY_LOCAL_MACHINE, RESPATH_D3D, &hKey)))
{
DWORD type;
DWORD value;
DWORD cb = sizeof(value);
pDeviceHandle->ForceFlagsOn = 0;
pDeviceHandle->ForceFlagsOff = 0;
#ifdef DEBUG
if (!RegQueryValueEx(hKey, "ForceDriverFlagsOn", NULL, &type, (CONST LPBYTE)&value, &cb))
{
pDeviceHandle->ForceFlagsOn = value;
}
cb = sizeof(value);
#endif
if (!RegQueryValueEx(hKey, "ForceDriverFlagsOff", NULL, &type, (CONST LPBYTE)&value, &cb))
{
pDeviceHandle->ForceFlagsOff = value;
}
RegCloseKey(hKey);
}
}
//
// D3D8ReenableDirectDrawObject
//
// On Win9X, this function doesn't do anything, but we have it since Win2K
// requires it and keeping it keeps the code bases more similar between the
// two platforms.
BOOL WINAPI D3D8ReenableDirectDrawObject( HANDLE hDD, LPBOOL pbNewMode )
{
*pbNewMode = TRUE;
return TRUE;
}
BOOL
SWCursorForced()
{
if (0 != GetPrivateProfileInt("Display", "SwCursor", 0, "SYSTEM.INI"))
{
// ini setting always takes precedence
DPF(2,"System.ini says SwCursor is ON");
return TRUE;
}
else
{
HKEY key;
if (RegOpenKey(HKEY_CURRENT_CONFIG, "Display\\Settings", &key) == ERROR_SUCCESS)
{
char temp[10];
DWORD len = sizeof(temp);
DWORD type;
DWORD i;
if ((RegQueryValueEx(key, "SwCursor", NULL, (LPDWORD)&type,
(LPBYTE)(LPSTR)temp, (LPDWORD)&len) == ERROR_SUCCESS) &&
(type == REG_SZ))
{
for (i = 0; i < len; i++)
{
if ( 0 == temp[i] )
break;
if ( '0' != temp[i] )
{
RegCloseKey(key);
DPF(2,"Regkey SwCursor is ON");
return TRUE;
}
}
}
RegCloseKey(key);
}
}
return FALSE;
}
//
// D3D8QueryDirectDrawObject
//
// This gets all of the actual HAL info. It will typically be called twice,
// the first time to get the basic info (some of the input pointers will be
// NULL), and again to get all of the info.
BOOL WINAPI D3D8QueryDirectDrawObject (HANDLE hDD,
PD3D8_DRIVERCAPS pDriverCaps,
PD3D8_CALLBACKS pCallbacks,
char *pDeviceName,
HINSTANCE hLibrary,
D3D8_GLOBALDRIVERDATA* pGblDriverData,
D3DHAL_D3DEXTENDEDCAPS* pExtendedCaps,
LPDDSURFACEDESC pTextureFormats,
LPDDPIXELFORMAT pZStencilFormats,
UINT* pcTextureFormats,
UINT* pcZStencilFormats
)
{
LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
LPDDRAWI_DIRECTDRAW_GBL pdrv;
DDSCAPSEX SurfCapsEx;
DWORD dwRet;
DWORD i;
HDC hdc;
D3DFORMAT* pTempZStencil;
PDDDEVICEHANDLE pDevice = (PDDDEVICEHANDLE) hDD;
DDHAL_GETDRIVERINFODATA GetDriverInfoData;
BOOL GotDX8Formats;
ENTER_DDRAW();
pdrv_lcl = pDevice->pDD->lpLcl;
pdrv = pdrv_lcl->lpGbl;
// Get all of the neccesary caps
memset(pDriverCaps, 0, sizeof(D3D8_DRIVERCAPS));
pDriverCaps->D3DCaps.Caps = pdrv->ddCaps.dwCaps;
pDriverCaps->D3DCaps.Caps2 = pdrv->ddCaps.dwCaps2;
pDriverCaps->D3DCaps.Caps3 = pdrv->ddCaps.dwSVCaps;
pDriverCaps->SVBCaps = pdrv->ddCaps.dwSVBCaps;
pDriverCaps->VSBCaps = pdrv->ddCaps.dwVSBCaps;
pDriverCaps->SVBCaps2 = pdrv->ddCaps.dwSVBCaps2;
SurfCapsEx.dwCaps2 = pdrv->ddsCapsMore.dwCaps2;
SurfCapsEx.dwCaps3 = pdrv->ddsCapsMore.dwCaps3;
SurfCapsEx.dwCaps4 = pdrv->ddsCapsMore.dwCaps4;
if (!IS_SOFTWARE_DRIVER(pDevice))
{
GotDX8Formats = FALSE;
// See if we can get the DX8 caps directly
if ((pdrv->dwFlags & DDRAWI_DRIVERINFO2) &&
(pdrv->pGetDriverInfo != NULL))
{
D3DCAPS8 caps8;
DD_GETDRIVERINFO2DATA* pgdi2;
memset(&caps8, 0, sizeof(caps8));
pgdi2 = (DD_GETDRIVERINFO2DATA*)&caps8;
// sizeof(DD_STEREOMODE)? The GUID for GetDriverInfo2 is shared with
// the stereo mode querying stuff. Therefore we need to pass down
// the structure size (and the expected data size) as
// sizeof(DD_STEREOMODE) even though we actually have a buffer (and
// expect a size of sizeof(D3DCAPS8).
pgdi2->dwReserved = sizeof(D3DCAPS8);
pgdi2->dwMagic = D3DGDI2_MAGIC;
pgdi2->dwType = D3DGDI2_TYPE_GETD3DCAPS8;
pgdi2->dwExpectedSize = sizeof(D3DCAPS8);
memset(&GetDriverInfoData, 0, sizeof(GetDriverInfoData));
GetDriverInfoData.dwSize = sizeof(GetDriverInfoData);
GetDriverInfoData.guidInfo = GUID_GetDriverInfo2;
GetDriverInfoData.lpvData = &caps8;
GetDriverInfoData.dwExpectedSize = sizeof(D3DCAPS8);
// 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.
GetDriverInfoData.dwContext = pdrv->dwReserved3;
if ((pdrv->pGetDriverInfo(&GetDriverInfoData) == DDHAL_DRIVER_HANDLED) &&
(GetDriverInfoData.ddRVal == DD_OK ))
{
// Looks like we got D3DCAPS8 back from the driver. Verify by means
// of the dwActualSize field in GetDriverInfoData.
if (sizeof(D3DCAPS8) != GetDriverInfoData.dwActualSize)
{
DPF(0, "Driver returned an data structure of incorrect size (!= sizeof(D3DCAPS8))");
LEAVE_DDRAW();
return(FALSE);
}
// All went well. Copy the caps data across
memcpy(&pDriverCaps->D3DCaps, &caps8, sizeof(caps8));
// Display drivers can all render windowed
if (pdrv->ddCaps.dwCaps2 & DDCAPS2_CANRENDERWINDOWED)
{
pDriverCaps->D3DCaps.Caps2 |= DDCAPS2_CANRENDERWINDOWED;
}
// Set the flag indicating that the DDI successfully reported DX8
// style caps
pDriverCaps->dwFlags |= DDIFLAG_D3DCAPS8;
}
}
// If this driver supports the DX8 DDI then use the new surface format reporting
// mechanism rather than the texture formats reported in the global driver data
if (pDriverCaps->dwFlags & DDIFLAG_D3DCAPS8)
{
DD_GETDRIVERINFO2DATA* pgdi2;
DD_GETFORMATCOUNTDATA gfcd;
DD_GETFORMATDATA gfd;
// If DDIFLAG_D3DCAPS8 got set we have a driver info 2 support
DDASSERT(pdrv->dwFlags & DDRAWI_DRIVERINFO2);
DDASSERT(pdrv->pGetDriverInfo != NULL);
// Step 1: Get the number of supported formats
// Please see the description comments above for a description of why the
// reserved field is set to sizeof(DD_STEREOMODE)
memset(&gfcd, 0, sizeof(gfcd));
gfcd.gdi2.dwReserved = sizeof(DD_GETFORMATCOUNTDATA);
gfcd.gdi2.dwMagic = D3DGDI2_MAGIC;
gfcd.gdi2.dwType = D3DGDI2_TYPE_GETFORMATCOUNT;
gfcd.gdi2.dwExpectedSize = sizeof(DD_GETFORMATCOUNTDATA);
#if DBG
// Ensure the driver actually sets the format count if it succeeds this call
gfcd.dwFormatCount = BOGUS_FIELD_VALUE;
#endif // DBG
memset(&GetDriverInfoData, 0, sizeof(GetDriverInfoData));
GetDriverInfoData.dwSize = sizeof(GetDriverInfoData);
GetDriverInfoData.guidInfo = GUID_GetDriverInfo2;
GetDriverInfoData.lpvData = &gfcd;
GetDriverInfoData.dwExpectedSize = sizeof(DD_GETFORMATCOUNTDATA);
GetDriverInfoData.dwContext = pdrv->dwReserved3;
if ((pdrv->pGetDriverInfo(&GetDriverInfoData) == DDHAL_DRIVER_HANDLED) &&
(GetDriverInfoData.ddRVal == DD_OK ))
{
// Looks like we got a DD_GETFORMATCOUNTDATA back from the driver. Verify by means
// of the dwActualSize field in GetDriverInfoData.
if (sizeof(DD_GETFORMATCOUNTDATA) != GetDriverInfoData.dwActualSize)
{
DPF(0, "Driver returned an data structure of incorrect size (!= sizeof(DD_GETFORMATCOUNTDATA))");
LEAVE_DDRAW();
return(FALSE);
}
#ifdef DBG
if (BOGUS_FIELD_VALUE == gfcd.dwFormatCount)
{
DPF_ERR( "Driver succeeded GETFORMATCOUNT request but didn't set dwFormatCount" );
LEAVE_DDRAW();
return(FALSE);
}
#endif // DBG
// All went well. Replace the number of supported texture formats the driver
// reported to us with this new number. We don't use the legacy texture format
// list if this new mechanism is supported
*pcTextureFormats = gfcd.dwFormatCount;
// Flag the fact that we got DX8 style formats from the driver.
GotDX8Formats = TRUE;
// Step2: Query for each of the surface formats in turn.
// We only do this if the caller requested that we do by means of a non-NULL
// texture format buffer
if (NULL != pTextureFormats)
{
DWORD c;
DDSURFACEDESC* pOutFormat;
// For simplicities sake we ask for a single format at a time. Not exactly
// high-performance but this should not matter at this stage of the code.
pOutFormat = pTextureFormats;
for (c = 0; c < (*pcTextureFormats); ++c)
{
// We reinitialize the entire request each time. We could probably
// optimize this but it doesn't seem worth it.
memset(&gfd, 0, sizeof(DD_GETFORMATDATA));
gfd.gdi2.dwReserved = sizeof(DD_GETFORMATDATA);
gfd.gdi2.dwMagic = D3DGDI2_MAGIC;
gfd.gdi2.dwType = D3DGDI2_TYPE_GETFORMAT;
gfd.gdi2.dwExpectedSize = sizeof(DD_GETFORMATDATA);
gfd.dwFormatIndex = c;
#if DBG
// Ensure the driver actually sets the format count if it succeeds this call
gfd.format.dwSize = BOGUS_FIELD_VALUE;
#endif // DBG
memset(&GetDriverInfoData, 0, sizeof(GetDriverInfoData));
GetDriverInfoData.dwSize = sizeof(GetDriverInfoData);
GetDriverInfoData.guidInfo = GUID_GetDriverInfo2;
GetDriverInfoData.lpvData = &gfd;
GetDriverInfoData.dwExpectedSize = sizeof(DD_GETFORMATDATA);
GetDriverInfoData.dwContext = pdrv->dwReserved3;
if ((pdrv->pGetDriverInfo(&GetDriverInfoData) == DDHAL_DRIVER_HANDLED) &&
(GetDriverInfoData.ddRVal == DD_OK ))
{
// Looks like we got a DD_GETFORMATDATA back from the driver. Verify by means
// of the dwActualSize field in GetDriverInfoData.
if (sizeof(DD_GETFORMATDATA) != GetDriverInfoData.dwActualSize)
{
DPF(0, "Driver returned an data structure of incorrect size (!= sizeof(DD_GETFORMATDATA))");
LEAVE_DDRAW();
return(FALSE);
}
DDASSERT(c == gfd.dwFormatIndex);
#ifdef DBG
if (BOGUS_FIELD_VALUE == gfd.format.dwSize)
{
DPF_ERR( "Driver succeeded GETFORMAT request but didn't set format" );
LEAVE_DDRAW();
return(FALSE);
}
#endif // DBG
// Looks like all went well so initialize the surface description
// part of the output format and copy the pixel format we got from
// the driver across
memset(pOutFormat, 0, sizeof(DDSURFACEDESC));
pOutFormat->dwSize = sizeof(DDSURFACEDESC);
pOutFormat->dwFlags = DDSD_PIXELFORMAT;
memcpy(&pOutFormat->ddpfPixelFormat, &(gfd.format), sizeof(DDPIXELFORMAT));
++pOutFormat;
}
}
}
}
else
{
DPF(0, "Driver claims DX8 but fails call to GETFORMATCOUNT" );
DPF(0, "DX7 texture format list will be used but this will change soon" );
DPF(0, "Fix driver to support DX8 style surface format reporting now" );
}
}
// The driver does not support the DX8 DDI so simply use the existing DX7
// style texture format list.
if (pdrv->lpD3DGlobalDriverData != NULL)
{
// Wackiness to get around type checking
*pGblDriverData = *(D3D8_GLOBALDRIVERDATA*) pdrv_lcl->lpGbl->lpD3DGlobalDriverData;
// If we alreay have DX8 style formats from the driver don't bother using the DX7
// style texture format list
if (!GotDX8Formats)
{
*pcTextureFormats = pdrv_lcl->lpGbl->lpD3DGlobalDriverData->dwNumTextureFormats;
if (pTextureFormats != NULL)
{
memcpy(
pTextureFormats,
pdrv_lcl->lpGbl->lpD3DGlobalDriverData->lpTextureFormats,
pdrv_lcl->lpGbl->lpD3DGlobalDriverData->dwNumTextureFormats*sizeof(*pTextureFormats));
}
}
// Get the D3D extended caps
if (pdrv->lpD3DExtendedCaps)
{
*pExtendedCaps = *(pdrv->lpD3DExtendedCaps);
}
}
else
{
// If we alreay have DX8 style formats from the driver don't bother using the DX7
// style texture format list
if (!GotDX8Formats)
{
*pcTextureFormats = 0;
}
}
// Get the supported Z formats. We only do this if we are not using a
// software driver
*pcZStencilFormats = pdrv->dwNumZPixelFormats;
if (pdrv->dwNumZPixelFormats > 0)
{
if (pZStencilFormats)
{
memcpy(pZStencilFormats,
pdrv->lpZPixelFormats,
pdrv->dwNumZPixelFormats * sizeof( *pZStencilFormats ));
}
}
else
{
if (pGblDriverData->hwCaps.dwDeviceZBufferBitDepth & DDBD_16)
{
(*pcZStencilFormats)++;
if (pZStencilFormats)
{
pZStencilFormats->dwSize = sizeof(DDPIXELFORMAT);
pZStencilFormats->dwFlags = DDPF_ZBUFFER;
pZStencilFormats->dwZBufferBitDepth = 16;
pZStencilFormats->dwStencilBitDepth = 0;
pZStencilFormats->dwZBitMask = 0xffff;
pZStencilFormats->dwStencilBitMask = 0x0000;
pZStencilFormats++;
}
}
if (pGblDriverData->hwCaps.dwDeviceZBufferBitDepth & DDBD_32)
{
(*pcZStencilFormats)++;
if (pZStencilFormats)
{
pZStencilFormats->dwSize = sizeof(DDPIXELFORMAT);
pZStencilFormats->dwFlags = DDPF_ZBUFFER;
pZStencilFormats->dwZBufferBitDepth = 32;
pZStencilFormats->dwStencilBitDepth = 0;
pZStencilFormats->dwZBitMask = 0xffffffff;
pZStencilFormats->dwStencilBitMask = 0x00000000;
pZStencilFormats++;
}
}
}
}
// Get info about the current mode
pDriverCaps->DisplayWidth = pdrv->vmiData.dwDisplayWidth;
pDriverCaps->DisplayHeight = pdrv->vmiData.dwDisplayHeight;
pDriverCaps->DisplayFrequency = pdrv->dwMonitorFrequency;
switch (pdrv->vmiData.ddpfDisplay.dwRGBBitCount)
{
case 8:
pDriverCaps->DisplayFormatWithAlpha = D3DFMT_P8;
pDriverCaps->DisplayFormatWithoutAlpha = D3DFMT_P8;
break;
case 15:
case 16:
if (pdrv->vmiData.ddpfDisplay.dwGBitMask == 0x7e0)
{
pDriverCaps->DisplayFormatWithAlpha = D3DFMT_R5G6B5;
pDriverCaps->DisplayFormatWithoutAlpha = D3DFMT_R5G6B5;
}
else
{
pDriverCaps->DisplayFormatWithAlpha = D3DFMT_X1R5G5B5;
pDriverCaps->DisplayFormatWithoutAlpha = D3DFMT_X1R5G5B5;
if (pdrv->vmiData.ddpfDisplay.dwFlags & DDPF_ALPHAPIXELS)
{
pDriverCaps->DisplayFormatWithAlpha = D3DFMT_A1R5G5B5;
}
//pdrv->vmiData.ddpfDisplay.dwRGBAlphaBitMask = 0;
//pdrv->vmiData.ddpfDisplay.dwFlags &= ~DDPF_ALPHAPIXELS;
}
break;
case 24:
pDriverCaps->DisplayFormatWithAlpha = D3DFMT_R8G8B8;
pDriverCaps->DisplayFormatWithoutAlpha = D3DFMT_R8G8B8;
break;
case 32:
pDriverCaps->DisplayFormatWithAlpha = D3DFMT_X8R8G8B8;
pDriverCaps->DisplayFormatWithoutAlpha = D3DFMT_X8R8G8B8;
if (pdrv->vmiData.ddpfDisplay.dwFlags & DDPF_ALPHAPIXELS)
{
pDriverCaps->DisplayFormatWithAlpha = D3DFMT_A8R8G8B8;
}
//pdrv->vmiData.ddpfDisplay.dwRGBAlphaBitMask = 0;
//pdrv->vmiData.ddpfDisplay.dwFlags &= ~DDPF_ALPHAPIXELS;
break;
default:
pDriverCaps->DisplayFormatWithAlpha = D3DFMT_UNKNOWN;
pDriverCaps->DisplayFormatWithoutAlpha = D3DFMT_UNKNOWN;
break;
}
pDevice->DisplayFormatWithAlpha = pDriverCaps->DisplayFormatWithAlpha;
pDevice->DisplayFormatWithoutAlpha = pDriverCaps->DisplayFormatWithoutAlpha;
// Fill in the D3D8 Callback table
RtlZeroMemory(pCallbacks, sizeof(*pCallbacks));
pCallbacks->CreateSurface = DdCreateSurface;
pCallbacks->DestroySurface = DdDestroySurface;
pCallbacks->Lock = DdLock;
pCallbacks->Unlock = DdUnlock;
pCallbacks->Blt = DdBlt;
pCallbacks->GetScanLine = DdGetScanLine;
pCallbacks->Flip = DdFlip;
pCallbacks->WaitForVerticalBlank = DdWaitForVerticalBlank;
pCallbacks->GetBltStatus = DdGetBltStatus;
pCallbacks->GetFlipStatus = DdGetFlipStatus;
pCallbacks->SetMode = DdSetMode;
pCallbacks->FlipToGDISurface = DdFlipToGDISurface;
pCallbacks->SetExclusiveMode = DdSetExclusiveMode;
pCallbacks->GetAvailDriverMemory = DdGetAvailDriverMemory;
pCallbacks->Clear2 = D3dClear;
pCallbacks->SetRenderTarget = D3dSetRenderTarget;
pCallbacks->SetColorkey = DdSetColorkey;
pCallbacks->SetPalette = DdSetPalette;
pCallbacks->UpdatePalette = DdUpdatePalette;
pCallbacks->SceneCapture = D3dSceneCapture;
if ((pdrv->lpD3DHALCallbacks != NULL) &&
(pdrv->lpD3DHALCallbacks->ContextCreate != NULL))
{
pCallbacks->CreateContext = D3dContextCreate;
}
if ((pdrv->lpD3DHALCallbacks != NULL) &&
(pdrv->lpD3DHALCallbacks->ContextDestroy != NULL))
{
pCallbacks->ContextDestroy = D3dContextDestroy;
}
if ((pdrv->lpD3DHALCallbacks != NULL) &&
(pdrv->lpD3DHALCallbacks->ContextDestroyAll != NULL))
{
pCallbacks->ContextDestroyAll = D3dContextDestroyAll;
}
if (pdrv->lpDDCBtmp->HALDDMiscellaneous2.GetDriverState != NULL)
{
pCallbacks->GetDriverState = D3dGetDriverState;
}
if ((pdrv->lpD3DHALCallbacks3 != NULL) &&
(pdrv->lpD3DHALCallbacks3->ValidateTextureStageState != NULL))
{
pCallbacks->ValidateTextureStageState = D3dValidateTextureStageState;
}
if ((pdrv->lpD3DHALCallbacks3 != NULL) &&
(pdrv->lpD3DHALCallbacks3->DrawPrimitives2 != NULL))
{
pCallbacks->DrawPrimitives2 = D3dDrawPrimitives2;
}
// If Refrast or the HEL has a hook, call it to let it change whatever it wants
if (IS_SOFTWARE_DRIVER(pDevice))
{
*pcZStencilFormats = 0;
SwDDIMungeCaps (
hLibrary,
hDD,
pDriverCaps,
pCallbacks,
pTextureFormats,
pcTextureFormats,
pDevice->pSwInitFunction
);
}
// Now we need to determine what level of DX support the driver supports
pDevice->DriverLevel = 0;
if (pDriverCaps->D3DCaps.MaxStreams != 0)
{
pDevice->DriverLevel = 8;
}
else if (pCallbacks->GetDriverState != 0)
{
pDevice->DriverLevel = 7;
}
else if (pCallbacks->DrawPrimitives2 != 0)
{
pDevice->DriverLevel = 6;
if (pDevice->pDefaultPalette == NULL)
{
PALETTEENTRY ColorTable[256];
int i;
for (i = 0; i < 256; i++)
{
ColorTable[i].peRed = (UCHAR) i;
ColorTable[i].peGreen = (UCHAR) i;
ColorTable[i].peBlue = (UCHAR) i;
}
DPF_MUTE();
DD_CreatePalette ((LPDIRECTDRAW) pDevice->pDD,
DDPCAPS_8BIT,
ColorTable,
&pDevice->pDefaultPalette,
NULL);
DPF_UNMUTE();
}
}
if (pGblDriverData->hwCaps.dwDevCaps & D3DDEVCAPS_TEXTURESYSTEMMEMORY)
{
pDevice->bCanTextureSysmem = TRUE;
}
// Can this driver handle lightweight surfaces?
pDriverCaps->KnownDriverFlags = 0;
if (pDevice->DriverLevel < 7)
{
pDevice->bLightweight = FALSE;
}
else if (pDevice->DriverLevel == 7)
{
pDevice->bLightweight = CanKnownDriverDoThis(pDevice, KNOWN_LIGHTWEIGHT);
}
else
{
pDevice->bLightweight = TRUE;
}
// What about HW cursor support?
// The check below needs to know the hardware driver level so it cannot use
// pDevice->DriverLevel since it may be set due to ref.
if (SWCursorForced())
{
pDriverCaps->D3DCaps.CursorCaps = 0;
}
else if (((0 == pdrv->lpD3DExtendedCaps) ||
(0 == pDriverCaps->D3DCaps.MaxStreams)) &&
(NULL != pdrv->lpDDCBtmp->HALDDMiscellaneous2.GetDriverState))
{
// The hardware driver is DX7
if (CanKnownDriverDoThis(pDevice, KNOWN_HWCURSOR))
{
pDriverCaps->D3DCaps.CursorCaps = D3DCURSORCAPS_COLOR;
pDriverCaps->KnownDriverFlags |= KNOWN_HWCURSOR;
if (CanKnownDriverDoThis(pDevice, KNOWN_HWCURSORLOWRES))
{
pDriverCaps->D3DCaps.CursorCaps |= D3DCURSORCAPS_LOWRES;
pDriverCaps->KnownDriverFlags |= KNOWN_HWCURSORLOWRES;
}
}
}
// If it's a pre-dx8 driver and they support cubemaps, we need to
// specify whether they support mipped cubemaps or not.
if (pDevice->DriverLevel < 8)
{
if (CanKnownDriverDoThis(pDevice, KNOWN_MIPPEDCUBEMAPS))
{
pDriverCaps->KnownDriverFlags |= KNOWN_MIPPEDCUBEMAPS;
}
// Does this driver have a Z/Stencil depth restriction?
if (CanKnownDriverDoThis(pDevice, KNOWN_ZSTENCILDEPTH))
{
pDriverCaps->KnownDriverFlags |= KNOWN_ZSTENCILDEPTH;
}
// Does device have no driver known to over-queue windowed presentation blts?
if (CanKnownDriverDoThis(pDevice, KNOWN_NOTAWINDOWEDBLTQUEUER))
{
pDriverCaps->KnownDriverFlags |= KNOWN_NOTAWINDOWEDBLTQUEUER;
}
// Does device support D3DFMT_D16_LOCKABLE
if (CanKnownDriverDoThis(pDevice, KNOWN_D16_LOCKABLE))
{
pDriverCaps->KnownDriverFlags |= KNOWN_D16_LOCKABLE;
}
// Figure out what RT/Texture formats it supports
if (CanKnownDriverDoThis(pDevice, KNOWN_CANMISMATCHRT))
{
pDriverCaps->KnownDriverFlags |= KNOWN_CANMISMATCHRT;
}
if (CanKnownDriverDoThis(pDevice, KNOWN_RTTEXTURE_X1R5G5B5))
{
pDriverCaps->KnownDriverFlags |= KNOWN_RTTEXTURE_X1R5G5B5;
}
if (CanKnownDriverDoThis(pDevice, KNOWN_RTTEXTURE_R5G6B5))
{
pDriverCaps->KnownDriverFlags |= KNOWN_RTTEXTURE_R5G6B5;
}
if (CanKnownDriverDoThis(pDevice, KNOWN_RTTEXTURE_X8R8G8B8))
{
pDriverCaps->KnownDriverFlags |= KNOWN_RTTEXTURE_X8R8G8B8;
}
if (CanKnownDriverDoThis(pDevice, KNOWN_RTTEXTURE_A8R8G8B8))
{
pDriverCaps->KnownDriverFlags |= KNOWN_RTTEXTURE_A8R8G8B8;
}
if (CanKnownDriverDoThis(pDevice, KNOWN_RTTEXTURE_A1R5G5B5))
{
pDriverCaps->KnownDriverFlags |= KNOWN_RTTEXTURE_A1R5G5B5;
}
if (CanKnownDriverDoThis(pDevice, KNOWN_RTTEXTURE_A4R4G4B4))
{
pDriverCaps->KnownDriverFlags |= KNOWN_RTTEXTURE_A4R4G4B4;
}
}
// ATI drivers don't handle palettes correctly, so we will delete
// all palettized textures from their list.
if (pDevice->DriverLevel < 8)
{
if (((pDevice->PCIID >> 16) == 0x1002) &&
(pTextureFormats != NULL))
{
i = 0;
while (i < *pcTextureFormats)
{
if (pTextureFormats[i].ddpfPixelFormat.dwFlags &
(DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8))
{
UINT j;
(*pcTextureFormats)--;
for (j = i; j < *pcTextureFormats; j++)
{
pTextureFormats[j] = pTextureFormats[j+1];
}
}
else
{
i++;
}
}
}
}
// We assume that a software driver will always support at least DX7
if ((pDevice->DriverLevel < 7) &&
IS_SOFTWARE_DRIVER(pDevice))
{
LEAVE_DDRAW();
DPF_ERR("A Software rasterizer must contain at least DX7 driver level support");
return FALSE;
}
LEAVE_DDRAW();
return TRUE;
}
VOID CleanupDevice (PDDDEVICEHANDLE pDevice)
{
DWORD i;
DDSURFACE* pSurf;
DDSURFACE* pSurfTemp;
// Cleanup the palette allocations
if (pDevice->pDefaultPalette != NULL)
{
InternalPaletteRelease((LPDDRAWI_DDRAWPALETTE_INT)
pDevice->pDefaultPalette);
pDevice->pDefaultPalette = NULL;
}
if (pDevice->NumPaletteHandleEntries > 0)
{
for (i = 0; i < pDevice->NumPaletteHandleEntries; i++)
{
if (pDevice->pPaletteHandleTable[i] != NULL)
{
InternalPaletteRelease((LPDDRAWI_DDRAWPALETTE_INT)
pDevice->pPaletteHandleTable[i]->pDDPalette);
MemFree(pDevice->pPaletteHandleTable[i]);
pDevice->pPaletteHandleTable[i] = NULL;
}
}
MemFree(pDevice->pPaletteHandleTable);
pDevice->pPaletteHandleTable = NULL;
pDevice->NumPaletteHandleEntries = 0;
}
if (pDevice->pContext)
{
D3D8_CONTEXTDESTROYDATA data;
data.dwhContext = (ULONG_PTR) pDevice->pContext;
D3dContextDestroy(&data);
pDevice->pContext = NULL;
}
pSurf = pDevice->pSurfList;
while (pSurf != NULL)
{
if (!IS_SOFTWARE_DRIVER_SURFACE(pSurf))
{
if (pSurf->dwFlags & DDSURFACE_LIGHTWEIGHT)
{
LPDDRAWI_DDRAWSURFACE_INT pHeavy;
pHeavy = MapLightweightSurface(pSurf);
if (pHeavy != NULL)
{
pHeavy->dwIntRefCnt = 1;
pHeavy->lpLcl->dwLocalRefCnt = 1;
pHeavy->lpLcl->lpGbl->dwRefCnt = 1;
if (pSurf->dwFlags & DDSURFACE_ROOT)
{
pHeavy->lpLcl->lpSurfMore->pAddrefedThisOwner = (IUnknown*) pSurf->pDevice->pDD;
}
InternalSurfaceRelease(pHeavy, TRUE, TRUE);
pHeavy->dwReserved1 = (ULONG_PTR) NULL;
pHeavy->dwReserved2 = 0;
}
MemFree (pSurf->Surface.pLight);
pSurf->Surface.pLight = NULL;
}
else if (pSurf->dwFlags & DDSURFACE_HEAVYWEIGHT)
{
if ((pSurf->dwFlags & DDSURFACE_ROOT) &&
(pSurf->Surface.pHeavy != NULL))
{
InternalSurfaceRelease(pSurf->Surface.pHeavy, FALSE, TRUE);
}
}
}
else
{
MemFree(pSurf->Surface.pHeavy);
}
pSurfTemp = pSurf;
pSurf = pSurf->pNext;
MemFree(pSurfTemp);
}
if (pDevice->pSwDD)
{
if (pDevice->pSwDD->lpLcl->lpGbl->lpDDCBtmp)
{
MemFree(pDevice->pSwDD->lpLcl->lpGbl->lpDDCBtmp);
}
MemFree(pDevice->pSwDD);
}
if (pDevice->NumCachedSurfaces > 0)
{
for (i = 0; i < (DWORD) pDevice->NumCachedSurfaces; i++)
{
MemFree(pDevice->pCachedSurfaceTable[i].pSurface);
}
MemFree(pDevice->pCachedSurfaceTable);
pDevice->pCachedSurfaceTable = NULL;
pDevice->NumCachedSurfaces = 0;
}
if (pDevice->SurfaceHandleList.dwList != NULL)
{
MemFree(pDevice->SurfaceHandleList.dwList);
}
}
VOID APIENTRY D3D8DeleteDirectDrawObject( HANDLE hDD )
{
PDDDEVICEHANDLE pDevice = (PDDDEVICEHANDLE) hDD;
LPDIRECTDRAW lpDD;
// hDD can be NULL in some error paths
if (pDevice == NULL)
return;
ENTER_DDRAW();
CleanupDevice(pDevice);
lpDD = (LPDIRECTDRAW) pDevice->pDD;
if (lpDD != NULL)
{
lpDD->lpVtbl->Release(lpDD);
}
if (pDeviceList == pDevice)
{
// If we're first, then update global list
// pointer
pDeviceList = pDevice->pLink;
}
else
{
// Find ourselves in the list
PDDDEVICEHANDLE pDevicePrev = pDeviceList;
while (pDevicePrev->pLink != pDevice)
{
pDevicePrev = pDevicePrev->pLink;
}
// Skip past our current node
pDevicePrev->pLink = pDevice->pLink;
}
MemFree(pDevice);
LEAVE_DDRAW();
}
HDC APIENTRY D3D8GetDC( HANDLE hSurface, LPPALETTEENTRY pPalette )
{
HDC hdc = NULL;
PDDSURFACE pSurf = (PDDSURFACE) hSurface;
LPDDRAWI_DDRAWSURFACE_INT pHeavy;
if (IS_SOFTWARE_DRIVER_SURFACE(pSurf))
{
DDSURFACEDESC ddsd;
ddsd.dwSize = sizeof(ddsd);
pHeavy = GetHeavyweightSurf(pSurf);
if (pHeavy == NULL)
{
hdc = NULL;
DPF_ERR("Out of memory error mapping lightweight surface");
}
else
{
FillDDSurfaceDesc(pHeavy->lpLcl, &ddsd);
ddsd.lpSurface = (void*)pHeavy->lpLcl->lpGbl->fpVidMem;
hdc = DD16_GetDC((HDC)(pSurf->pDevice->pDD->lpLcl->hDC),
&ddsd,
NULL);
if (hdc == NULL)
{
DPF_ERR("Failure to GetDC for non-heavyweight surface?");
}
DONE_HEAVYWEIGHT_SURF (pSurf);
}
}
else
{
pHeavy = GetHeavyweightSurf(pSurf);
if (pHeavy == NULL)
{
DPF_ERR("Unable to map lightweight surface - out of memory");
hdc = NULL;
}
else
{
HRESULT hr = InternalGetDC(pHeavy, &hdc, FALSE);
if (FAILED(hr))
{
DPF_ERR("Could not get DC for surface");
hdc = NULL;
}
}
}
return hdc;
}
BOOL APIENTRY D3D8ReleaseDC(HANDLE hSurface, HDC hdc)
{
PDDSURFACE pSurf = (PDDSURFACE) hSurface;
DDASSERT(hdc != NULL);
if (IS_SOFTWARE_DRIVER_SURFACE(pSurf))
{
DD16_ReleaseDC(hdc);
}
else
{
HRESULT hr;
LPDDRAWI_DDRAWSURFACE_INT pHeavy;
if (pSurf->dwFlags & DDSURFACE_LIGHTWEIGHT)
{
pHeavy = GET_CACHED_LIGHTWEIGHT_INT(pSurf);
DDASSERT(pHeavy != NULL);
}
else
{
pHeavy = pSurf->Surface.pHeavy;
}
hr = InternalReleaseDC(pHeavy->lpLcl, hdc, FALSE);
if (FAILED(hr))
{
DPF_ERR("Could not release DC?");
}
DONE_HEAVYWEIGHT_SURF(pSurf);
}
return TRUE;
}
BOOL APIENTRY D3D8SetGammaRamp( HANDLE hDD, HDC hdc, LPVOID lpGammaRamp )
{
PDDDEVICEHANDLE pDevice = (PDDDEVICEHANDLE) hDD;
HRESULT hr = E_FAIL;
ENTER_BOTH();
if (CheckForDeviceLost(hDD))
{
LEAVE_BOTH();
return TRUE;
}
if (pDevice->pDD->lpLcl->lpPrimary != NULL)
{
hr = DD_Gamma_SetGammaRamp((LPDIRECTDRAWGAMMACONTROL) pDevice->pDD->lpLcl->lpPrimary,
0, lpGammaRamp);
}
LEAVE_BOTH();
if (SUCCEEDED(hr))
{
return TRUE;
}
return FALSE;
}
// D3D8BuildModeTable
//
VOID APIENTRY D3D8BuildModeTable( char* pDeviceName,
D3DDISPLAYMODE* pTable,
DWORD* pNumEntries,
D3DFORMAT Unknown16,
HANDLE hProfile,
BOOL b16bppSupported,
BOOL b32bppSupported
)
{
PDDDEVICEHANDLE pDeviceHandle = (PDDDEVICEHANDLE) hProfile;
LPDDRAWI_DIRECTDRAW_GBL pdrv;
DWORD NumModes = 0;
DWORD i;
DWORD j;
D3DFORMAT format;
if ((pDeviceHandle == NULL) ||
(pDeviceHandle->pDD == NULL))
{
*pNumEntries = NumModes;
return;
}
ENTER_DDRAW();
pdrv = pDeviceHandle->pDD->lpLcl->lpGbl;
NumModes = 0;
for (i = 0; i < pdrv->dwNumModes; i++)
{
// Filter out all modes other than 15, 16 and 32bpp
if ((pdrv->lpModeInfo[i].dwBPP != 15) &&
(pdrv->lpModeInfo[i].dwBPP != 16) &&
(pdrv->lpModeInfo[i].dwBPP != 32))
{
continue;
}
if (((pdrv->lpModeInfo[i].dwBPP == 15) ||
(pdrv->lpModeInfo[i].dwBPP == 16)) &&
!b16bppSupported)
{
continue;
}
else if ((pdrv->lpModeInfo[i].dwBPP == 32) &&
!b32bppSupported)
{
continue;
}
// Can GDI and the monitor handle this mode/refresh rate?
if(pdrv->dwFlags & DDRAWI_DISPLAYDRV)
{
DWORD cds_flags;
DEVMODE dm;
int cds_rc;
BOOL bUseRefresh;
bUseRefresh = (pdrv->lpModeInfo[i].wRefreshRate > 0);
makeDEVMODE( pdrv, &pdrv->lpModeInfo[i], FALSE, bUseRefresh, &cds_flags, &dm );
cds_flags |= CDS_TEST;
cds_rc = xxxChangeDisplaySettingsExA(pdrv->cDriverName, &dm, NULL, cds_flags, 0);
if( cds_rc != 0 )
{
continue;
}
if (!MonitorCanHandleMode (pdrv,
pdrv->lpModeInfo[i].dwWidth,
pdrv->lpModeInfo[i].dwHeight,
pdrv->lpModeInfo[i].wRefreshRate))
{
continue;
}
}
// Make sure that we understand the format.
if ((pdrv->lpModeInfo[i].dwBPP == 16) ||
(pdrv->lpModeInfo[i].dwBPP == 15))
{
format = Unknown16;
}
else
{
DDASSERT(pdrv->lpModeInfo[i].dwBPP == 32);
format = D3DFMT_X8R8G8B8;
}
// Add the new mode.
if (pTable != NULL)
{
///The caller must pass us a number
DDASSERT( (*pNumEntries) );
if ( NumModes >= *pNumEntries )
{
//we exceeded the number of entries allocated for us.
//tell the caller to re-query and try again.
NumModes = 0;
break;
}
pTable[NumModes].Width = pdrv->lpModeInfo[i].dwWidth;
pTable[NumModes].Height = pdrv->lpModeInfo[i].dwHeight;
pTable[NumModes].RefreshRate = pdrv->lpModeInfo[i].wRefreshRate;
pTable[NumModes].Format = format;
}
NumModes++;
}
LEAVE_DDRAW();
*pNumEntries = NumModes;
}
BOOL APIENTRY D3D8IsDeviceLost( HANDLE hDD)
{
PDDDEVICEHANDLE pDevice = (PDDDEVICEHANDLE) hDD;
return pDevice->bDeviceLost;
}
BOOL APIENTRY D3D8CanRestoreNow( HANDLE hDD)
{
PDDDEVICEHANDLE pDevice = (PDDDEVICEHANDLE) hDD;
LPDDRAWI_DIRECTDRAW_GBL pGbl;
BOOL bSupported = FALSE;
HRESULT hr;
// If we aren't lost, then it's an easy call
ENTER_DDRAW();
if (!(pDevice->bDeviceLost))
{
LEAVE_DDRAW();
return TRUE;
}
hr = DD_TestCooperativeLevel((LPDIRECTDRAW)pDevice->pDD);
if ( DD_OK == hr || DDERR_WRONGMODE == hr)
{
// Are we in a mode in which D3D is supported?
pGbl = pDevice->pDD->lpLcl->lpGbl;
if (IS_SOFTWARE_DRIVER(hDD))
{
// Assume that any software driver can render in modes > 8bpp
if (pGbl->vmiData.ddpfDisplay.dwRGBBitCount > 8)
{
bSupported = TRUE;
}
}
if (pGbl->lpD3DGlobalDriverData != NULL)
{
switch (pGbl->vmiData.ddpfDisplay.dwRGBBitCount)
{
case 15:
case 16:
if (pGbl->lpD3DGlobalDriverData->hwCaps.dwDeviceRenderBitDepth & DDBD_16)
{
bSupported = TRUE;
}
break;
case 24:
if (pGbl->lpD3DGlobalDriverData->hwCaps.dwDeviceRenderBitDepth & DDBD_24)
{
bSupported = TRUE;
}
break;
case 32:
if (pGbl->lpD3DGlobalDriverData->hwCaps.dwDeviceRenderBitDepth & DDBD_32)
{
bSupported = TRUE;
}
break;
}
}
}
LEAVE_DDRAW();
return bSupported;
}
VOID APIENTRY D3D8RestoreDevice( HANDLE hDD)
{
HRESULT hr;
DWORD i, j, k;
DWORD Width, Height, Depth;
BYTE *SliceSrc, *SliceDst, *RowSrc, *RowDst;
PDDDEVICEHANDLE pDevice = (PDDDEVICEHANDLE) hDD;
PDDSURFACE pSurf;
LPDDRAWI_DDRAWSURFACE_INT pHeavy;
PDEFERREDCREATE pDefCreate = pDevice->pDeferList;
PDEFERREDCREATE *ppNext = &pDevice->pDeferList;
PDEFERREDCREATE pTemp;
D3D8_LOCKDATA LockData;
D3D8_UNLOCKDATA UnlockData;
ENTER_BOTH();
if (!D3D8CanRestoreNow(hDD))
{
LEAVE_BOTH();
return;
}
pDevice->bDeviceLost = FALSE;
pDevice->bDP2Error = FALSE;
// If a context was created while lost, we will not re-create it now since
// we don't have a render target or Z Buffer (the vidmem surfaces would have
// already been destroyed. Therefore, we won't attempt to create the context
// until they create the new surfaces and call SetRenderTarget. We also
// won't try to create any defered texture handles at this time since we may
// not have a valid context. We will also do that in the SetRenderTarget call.
// Walk the list of surfaces and create any SurfaceEx surfaces that we may
// have pending.
pSurf = pDevice->pSurfList;
while (pSurf != NULL)
{
if ((pSurf->dwFlags & DDSURFACE_DEFERCREATEEX) &&
!(pSurf->dwFlags & DDSURFACE_DUMMY))
{
pHeavy = GetHeavyweightSurf(pSurf);
if (pHeavy != NULL)
{
createsurfaceEx(pHeavy->lpLcl);
DONE_HEAVYWEIGHT_SURF(pSurf);
}
pSurf->dwFlags &= ~DDSURFACE_DEFERCREATEEX;
}
pSurf = pSurf->pNext;
}
// Finally resurrect our deferred driver managed surfaces (Gulp!)
while (pDefCreate != NULL)
{
// First check if the deferred surface exists at all. The problem
// is that DdDestroySurface could have been called. We could have
// removed the surface from the deferred list in DdDestroySurface
// but since DdDestroySurface is called piecemeal, it gets
// very annoying. The removal is best done here.
// ASSUMPTION: if pSList[0].hKernelHandle is NULL then
// pSList[1,2,etc].hKernelHandle are also NULL. There is no
// reason for this to be not the case as of 3/2001.
if (pDefCreate->CreateData.pSList[0].hKernelHandle == NULL)
{
pTemp = pDefCreate->pNext;
*ppNext = pTemp;
MemFree(pDefCreate->CreateData.pSList);
MemFree(pDefCreate);
pDefCreate = pTemp;
continue;
}
// Attempt to resurrect
pDefCreate->CreateData.bReUse = TRUE;
hr = DdCreateSurface(&pDefCreate->CreateData);
if (SUCCEEDED(hr))
{
for (i = 0; i < pDefCreate->CreateData.dwSCnt; i++)
{
pSurf = (PDDSURFACE) pDefCreate->CreateData.pSList[i].hKernelHandle;
// Reset DDSURF_SYSMEMALLOCATED to keep DdLock below happy
pSurf->dwFlags &= ~DDSURFACE_SYSMEMALLOCATED;
// Lock and copy
ZeroMemory(&LockData, sizeof(LockData));
LockData.hDD = hDD;
LockData.hSurface = pSurf;
hr = DdLock(&LockData);
if (SUCCEEDED(hr))
{
SliceSrc = (BYTE*)pSurf->fpVidMem;
SliceDst = (BYTE*)LockData.lpSurfData;
Width = pDefCreate->CreateData.pSList[i].cpWidth;
Height = pDefCreate->CreateData.pSList[i].cpHeight;
Depth = pDefCreate->CreateData.pSList[i].cpDepth;
if (!(pDefCreate->CreateData.Type == D3DRTYPE_VOLUME ||
pDefCreate->CreateData.Type == D3DRTYPE_VOLUMETEXTURE))
{
Depth = 1;
}
for (j = 0; j < Depth; ++j)
{
RowSrc = SliceSrc;
RowDst = SliceDst;
for (k = 0; k < Height; ++k)
{
CopyMemory(RowDst, RowSrc, min(LockData.lPitch, (LONG)Width * 8));
RowSrc += Width * 8;
RowDst += LockData.lPitch;
}
SliceSrc += Width * Height * 8;
SliceDst += LockData.lSlicePitch;
}
ZeroMemory(&UnlockData, sizeof(UnlockData));
UnlockData.hDD = hDD;
UnlockData.hSurface = pSurf;
hr = DdUnlock(&UnlockData);
if (FAILED(hr))
{
// TODO: Handle/(ignore?) failure
DPF(0,"Unlock failed when resurrecting driver managed surface.");
}
}
else
{
// TODO: Handle/(ignore?) failure
DPF(0,"Lock failed when resurrecting driver managed surface. Texture may go missing.");
}
// Free the temporary fpVidmem that we allocated in CreateVidmemSurface
MemFree(pSurf->fpVidMem);
pSurf->fpVidMem = 0;
}
// Remove from list and freeup all memory
pTemp = pDefCreate->pNext;
*ppNext = pTemp;
MemFree(pDefCreate->CreateData.pSList);
MemFree(pDefCreate);
pDefCreate = pTemp;
}
else
{
// We set ReUse to FALSE to indicate that we were not able to resurrect
pDefCreate->CreateData.bReUse = FALSE;
ppNext = &(pDefCreate->pNext);
pDefCreate = pDefCreate->pNext;
}
}
if (pDevice->pDeferList != NULL)
{
// TODO:
// Ummm, we were not able to resurrect. This may be due to out of memory
// which probably needs to be reported to the app.
DPF(0,"Unable to resurrect all driver managed surfaces.");
}
LEAVE_BOTH();
}
BOOL APIENTRY D3D8DoVidmemSurfacesExist( HANDLE hDD)
{
PDDDEVICEHANDLE pDeviceHandle = (PDDDEVICEHANDLE) hDD;
PDDSURFACE pSurf;
// Walk the list and return TRUE is we find any surfaces that are either
// local or nonlocal vidmem.
ENTER_DDRAW();
pSurf = pDeviceHandle->pSurfList;
while (pSurf != NULL)
{
if ((pSurf->Pool == D3DPOOL_LOCALVIDMEM) ||
(pSurf->Pool == D3DPOOL_NONLOCALVIDMEM) ||
(pSurf->dwFlags & DDSURFACE_TREATASVIDMEM))
{
#if DBG
DPF(0,"The following D3DPOOL_DEFAULT surfaces/buffers/textures still exist");
pSurf = pDeviceHandle->pSurfList;
while (pSurf != NULL)
{
if ((pSurf->Pool == D3DPOOL_LOCALVIDMEM) ||
(pSurf->Pool == D3DPOOL_NONLOCALVIDMEM) ||
(pSurf->dwFlags & DDSURFACE_TREATASVIDMEM))
{
switch (pSurf->Type)
{
case D3DRTYPE_SURFACE:
DPF(0," D3DRTYPE_SURFACE");
break;
case D3DRTYPE_VOLUME:
DPF(0," D3DRTYPE_VOLUME");
break;
case D3DRTYPE_TEXTURE:
DPF(0," D3DRTYPE_TEXTURE");
break;
case D3DRTYPE_VOLUMETEXTURE:
DPF(0," D3DRTYPE_VOLUMETEXTURE");
break;
case D3DRTYPE_CUBETEXTURE:
DPF(0," D3DRTYPE_CUBETEXTURE");
break;
case D3DRTYPE_VERTEXBUFFER:
DPF(0," D3DRTYPE_VERTEXBUFFER");
break;
case D3DRTYPE_INDEXBUFFER:
DPF(0," D3DRTYPE_INDEXBUFFER");
break;
case D3DRTYPE_COMMANDBUFFER:
DPF(0," D3DRTYPE_COMMANDBUFFER");
break;
default:
DPF(0," UNKNOWN SURFACE TYPE");
break;
}
}
pSurf = pSurf->pNext;
}
#endif
LEAVE_DDRAW();
return TRUE;
}
pSurf = pSurf->pNext;
}
LEAVE_DDRAW();
return FALSE;
}
DWORD APIENTRY D3D8GetMode( HANDLE Handle,
char* pDeviceName,
D3DDISPLAYMODE* pMode,
D3DFORMAT Unknown16)
{
PDDDEVICEHANDLE pDeviceHandle = (PDDDEVICEHANDLE) Handle;
LPDDRAWI_DIRECTDRAW_GBL pdrv;
ENTER_DDRAW();
memset(pMode, 0, sizeof(D3DDISPLAYMODE));
if (pDeviceHandle != NULL)
{
pdrv = pDeviceHandle->pDD->lpLcl->lpGbl;
pMode->Width = pdrv->vmiData.dwDisplayWidth;
pMode->Height = pdrv->vmiData.dwDisplayHeight;
pMode->RefreshRate = pdrv->dwMonitorFrequency;
switch (pdrv->vmiData.ddpfDisplay.dwRGBBitCount)
{
case 8:
pMode->Format = D3DFMT_P8;
break;
case 15:
case 16:
if (pdrv->vmiData.ddpfDisplay.dwGBitMask == 0x7e0)
{
pMode->Format = D3DFMT_R5G6B5;
}
else
{
pMode->Format = D3DFMT_X1R5G5B5;
}
break;
case 24:
pMode->Format = D3DFMT_R8G8B8;
break;
case 32:
pMode->Format = D3DFMT_X8R8G8B8;
break;
default:
pMode->Format = D3DFMT_UNKNOWN;
break;
}
LEAVE_DDRAW();
return DD_OK;
}
else
{
DEVMODE dm;
HDC hdc;
memset (&dm, 0, sizeof(dm));
dm.dmSize = sizeof(dm);
// For pre-Win98 systems, we use GetDeviceCaps
// because ENUM_CURRENT_SETTINGS is not
// supported on these legacy systems.
if (!IsWindows98())
{
DWORD bpp;
hdc = GetDC(NULL);
pMode->Width = GetDeviceCaps(hdc, HORZRES);
pMode->Height = GetDeviceCaps(hdc, VERTRES);
pMode->RefreshRate = 0;
bpp = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES);
ReleaseDC(NULL, hdc);
switch (bpp)
{
case 8:
pMode->Format = D3DFMT_P8;
break;
case 24:
pMode->Format = D3DFMT_R8G8B8;
break;
case 32:
pMode->Format = D3DFMT_X8R8G8B8;
break;
case 15:
case 16:
pMode->Format = Unknown16;
break;
default:
DPF(0, "Unknown desktop format");
pMode->Format = D3DFMT_UNKNOWN;
break;
}
}
else if (EnumDisplaySettings(pDeviceName, ENUM_CURRENT_SETTINGS, &dm))
{
pMode->Width = dm.dmPelsWidth;
pMode->Height = dm.dmPelsHeight;
pMode->RefreshRate = dm.dmDisplayFrequency;
switch (dm.dmBitsPerPel)
{
case 8:
pMode->Format = D3DFMT_P8;
break;
case 24:
pMode->Format = D3DFMT_R8G8B8;
break;
case 32:
pMode->Format = D3DFMT_X8R8G8B8;
break;
case 15:
case 16:
pMode->Format = Unknown16;
break;
default:
pMode->Format = D3DFMT_UNKNOWN;
break;
}
}
else
{
LEAVE_DDRAW();
DPF_ERR("EnumDisplaySettings failed?");
DPF(0, "display is %s", pDeviceName);
return D3DERR_DRIVERINTERNALERROR;
}
LEAVE_DDRAW();
return DD_OK;
}
LEAVE_DDRAW();
return D3DERR_DRIVERINTERNALERROR;
}
DWORD APIENTRY D3D8SetMode( HANDLE Handle,
char* pDeviceName,
UINT Width,
UINT Height,
UINT BPP,
UINT RefreshRate,
BOOL bRestore)
{
PDDDEVICEHANDLE pDeviceHandle = (PDDDEVICEHANDLE) Handle;
LPDDRAWI_DIRECTDRAW_GBL pdrv;
HRESULT hr = DDERR_GENERIC;
DWORD i;
ENTER_DDRAW();
if ((pDeviceHandle != NULL) &&
(pDeviceHandle->pDD != NULL))
{
// We will call DDraw to do the mode change because it is able to
// cleanup the mode change when the app exits and because we don't
// want to treat external mode changes and DDraw mode changes the
// same way.
pdrv = pDeviceHandle->pDD->lpLcl->lpGbl;
for (i = 0; i < pdrv->dwNumModes; i++)
{
if ((pdrv->lpModeInfo[i].dwWidth == Width) &&
(pdrv->lpModeInfo[i].dwHeight == Height) &&
(pdrv->lpModeInfo[i].dwBPP == BPP))
{
if ((RefreshRate == 0) ||
(RefreshRate == pdrv->lpModeInfo[i].wRefreshRate))
{
break;
}
}
}
if (i < pdrv->dwNumModes)
{
BOOL bExists;
BOOL bOwn;
LPDDRAWI_DIRECTDRAW_LCL lcl = pDeviceHandle->pDD->lpLcl;
// When profiling, we will be doing mode changes w/o holding
// exlusive mode, but we need ddraw to think that we have it in
// order to change bit depth.
CheckExclusiveMode(lcl, &bExists, &bOwn, FALSE, NULL, FALSE);
if (!bOwn)
{
if (bExists)
{
LEAVE_DDRAW();
return D3DERR_DRIVERINTERNALERROR;
}
lcl->lpGbl->lpExclusiveOwner = lcl;
}
if (bRestore)
{
hr = MapLegacyResult(RestoreDisplayMode (lcl, TRUE));
}
else
{
hr = MapLegacyResult(SetDisplayMode (lcl,
i,
TRUE,
RefreshRate != 0));
}
if (!bOwn)
{
// This check shouldn't be needed, but it's safe since just
// about anything can happen during a mode change.
if (lcl->lpGbl->lpExclusiveOwner == lcl)
{
lcl->lpGbl->lpExclusiveOwner = NULL;
}
}
}
}
LEAVE_DDRAW();
return hr;
}
DWORD APIENTRY D3D8SetCooperativeLevel(
HANDLE hDD,
HWND hWnd,
DWORD dwFlags )
{
PDDDEVICEHANDLE pDevice = (PDDDEVICEHANDLE) hDD;
LPDDRAWI_DIRECTDRAW_INT pdrv_int = pDevice->pDD;
return MapLegacyResult(DD_SetCooperativeLevel((LPDIRECTDRAW)pdrv_int, hWnd, dwFlags|DDSCL_DX8APP));
}
BOOL APIENTRY D3D8IsDummySurface(
HANDLE hSurface )
{
PDDSURFACE pSurf = (PDDSURFACE) hSurface;
return ((pSurf->dwFlags & DDSURFACE_DUMMY) != 0);
}
void CleanupD3D8( LPDDRAWI_DIRECTDRAW_GBL pdrv,
BOOL bDestroyAll,
DWORD PID)
{
DDDEVICEHANDLE* pDevice;
DDDEVICEHANDLE* pTemp;
ENTER_DDRAW();
pDevice = pDeviceList;
if (bDestroyAll)
{
// The process has died, so clean everything up. We don't need to call
// the software driver for anything since it's already unloaded.
while (pDevice != NULL)
{
if (pDevice->PID == PID)
{
CleanupDevice(pDevice);
// Remove this device from the list
if (pDeviceList == pDevice)
{
pDeviceList = pDevice->pLink;
}
else
{
pTemp = pDeviceList;
while (pTemp->pLink != pDevice)
{
pTemp = pTemp->pLink;
}
pTemp->pLink = pDevice->pLink;
}
// Now free the device
pTemp = pDevice;
pDevice = pDevice->pLink;
MemFree(pTemp);
}
else
{
pDevice = pDevice->pLink;
}
}
}
else
{
// The device is getting lost, so we will mark it as lost and free up
// any resources that will get lost.
while (pDevice != NULL)
{
if (pDevice->pDD->lpLcl->lpGbl == pdrv)
{
LoseDevice (pDevice);
}
pDevice = pDevice->pLink;
}
}
LEAVE_DDRAW();
}
VOID APIENTRY D3D8LoseDevice(
HANDLE hDD )
{
ENTER_DDRAW();
LoseDevice (hDD);
LEAVE_DDRAW();
}
VOID APIENTRY D3D8GetHALName(
char* pDisplayName,
char* pHALName)
{
LPDDRAWI_DIRECTDRAW_INT lpDD_int = NULL;
ENTER_DDRAW();
InternalDirectDrawCreate( NULL,
(LPDIRECTDRAW*) &lpDD_int,
NULL,
DDRAWILCL_DIRECTDRAW7 | DDRAWILCL_DIRECTDRAW8,
pDisplayName);
if (lpDD_int != NULL)
{
lstrcpy(pHALName, lpDD_int->lpLcl->lpGbl->dd32BitDriverData.szName);
DD_Release((LPDIRECTDRAW)lpDD_int);
}
LEAVE_DDRAW();
}