|
|
/*==========================================================================
* * 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(); }
|