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