/******************************Module*Header*******************************\ * Module Name: ddraw.c * * Client side stubs for the private DirectDraw system APIs. * * Created: 3-Dec-1995 * Author: J. Andrew Goossen [andrewgo] * * Copyright (c) 1995-1999 Microsoft Corporation \**************************************************************************/ #define _D3DTYPES_H_ #define _D3DCAPS_H_ #include "ddrawpr.h" //#include "ddrawgdi.h" #include #include #include #include #include "ddithunk.h" #include #include #define _FACD3D 0x876 #define MAKE_D3DHRESULT( code ) MAKE_HRESULT( 1, _FACD3D, code ) #define D3DERR_DEVICELOST MAKE_D3DHRESULT(2152) #define D3DERR_DRIVERINTERNALERROR MAKE_D3DHRESULT(2087) #define D3DERR_NOTAVAILABLE MAKE_D3DHRESULT(2154) #define D3DERR_OUTOFVIDEOMEMORY MAKE_D3DHRESULT(380) #define D3DERR_DEFERRED_DP2ERROR MAKE_D3DHRESULT(2158) typedef struct _KNOWNENTRY { DWORD PCIID; DWORD VersionMajor; // 0 means all versions DWORD VersionMinor; // 0 means all versions DWORD Flags; } KNOWNENTRY; // The buffer used by GetDriverInfo2 is constrained to the maximum size // specified below by restrictions in the Win2K kernel. It is vital that // all data passed to the driver and received from the driver via // GetDriverInfo2 fit within a buffer of this number of DWORDS. // This size has to be less than 1K to let the kernel do its own buffer // overwrite testing. #define MAX_GDI2_BUFFER_DWORD_SIZE (249) // Bogus value used to initialize write only fields when communicating // with the driver in debug builds #define BOGUS_FIELD_VALUE 0xBAADCAFEul // Some global variables used to track when surfaces are free for all devices // in the process. This is tricky since we don't keep a device list. DWORD GlobalUniqueness = 0; DWORD NumDevices = 0; DWORD NumReadyDevices = 0; //todo d16 for rage 128 series... need date/time //todo :G200, G400 new RT+Tex formats... need date/time //todo: Need driver date/time for Kyro: |KNOWN_CANMISMATCHRT|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8 //todo: Trident 8420, 9910: need date/time for D16 //todo: dates for SiS parts D16 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, 0x0005000a, 0x00000404, 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, 0x0005000a, 0x00000404, 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, 0x00050001, 0x098a0001, 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, 0x00050001, 0x098a0001, 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, 0x00050001, 0x098a0001, 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, 0x00050001, 0x098a0001, 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, 0x00050001, 0x098a0001, 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, 0x00050001, 0x098a0001, 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, 0x00050001, 0x098a0001, 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, 0x00050001, 0x098a0001, 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, 0x00050001, 0x098a0001, 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, 0x00050001, 0x098a0001, 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, 0x00050001, 0x098a0001, 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, 0x00050001, 0x098a0001, 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, 0x00050001, 0x098a0001, 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, 0x00050001, 0x098a0001, 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, 0x00050001, 0x098a0001, 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, 0x00050001, 0x098a0001, 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, 0x00050001, 0x098a0001, 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, 0x00050001, 0x098a0001, 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, 0x00050001, 0x098a0001, 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, 0x00050001, 0x098a0001, 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, 0x00050001, 0x098a0001, 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, 0x00050001, 0x098a0001, 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, 0x00050001, 0x098a0001, 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, 0x00050001, 0x098a0001, 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, 0x00050001, 0x098a0001, 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, 0x00050001, 0x098a0001, 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, 0x00050001, 0x098a0001, 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, 0x00050001, 0x098a0001, 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, 0x00050001, 0x098a0001, 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, 0x00050001, 0x098a0001, 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, 0x00050001, 0x098a0001, 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, 0x00050001, 0x098a0001, 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, 0x00050001, 0x098a0001, 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, 0x00050001, 0x098a0001, 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, 0x00050001, 0x098a0001, 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, 0x00050001, 0x098a0001, 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, 0x00050001, 0x098a0001, 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, 0x00050001, 0x098a0001, 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, 0x00050001, 0x098a0001, 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, 0x0005000c, 0x000104b0, 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, 0x0005000c, 0x000104b0, 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, 0x0005000c, 0x000104b0, 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 {0x3d3d000a, 0x00050000, 0x08930001, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // Perm3 {0x3d3d000c, 0x00050000, 0x08930001, KNOWN_CANMISMATCHRT|KNOWN_ZSTENCILDEPTH|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_A4R4G4B4|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, 0x0005000c, 0x0001044c, KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_CANMISMATCHRT|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // SiS 300 {0x10390300, 0, 0, KNOWN_ZSTENCILDEPTH|KNOWN_CANMISMATCHRT|KNOWN_RTTEXTURE_R5G6B5}, // SiS 300 {0x10396326, 0x0005000c, 0x00010514, KNOWN_ZSTENCILDEPTH|KNOWN_NOTAWINDOWEDBLTQUEUER|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_R5G6B5}, // SiS 6326 {0x10396326, 0, 0, KNOWN_ZSTENCILDEPTH|KNOWN_NOTAWINDOWEDBLTQUEUER }, // SiS 6326 {0x10395300, 0x0005000c, 0x0001044c, KNOWN_ZSTENCILDEPTH|KNOWN_D16_LOCKABLE|KNOWN_CANMISMATCHRT|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_R5G6B5|KNOWN_RTTEXTURE_A1R5G5B5|KNOWN_RTTEXTURE_A4R4G4B4|KNOWN_RTTEXTURE_X8R8G8B8|KNOWN_RTTEXTURE_A8R8G8B8}, // SiS 300 {0x10395300, 0, 0, KNOWN_ZSTENCILDEPTH|KNOWN_CANMISMATCHRT|KNOWN_RTTEXTURE_R5G6B5}, // SiS 300 {0x10396300, 0x0005000c, 0x0001044c, 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 {0x10396300, 0, 0, KNOWN_ZSTENCILDEPTH|KNOWN_CANMISMATCHRT|KNOWN_RTTEXTURE_X1R5G5B5|KNOWN_RTTEXTURE_R5G6B5}, // SiS 6300 {0x10390310, 0x0005000d, 0x0001035c, 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 310 {0x10390315, 0x0005000d, 0x0001035c, 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 315 {0x10390325, 0x0005000d, 0x000107d0, 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 325 {0x10396325, 0x0005000d, 0x000107d0, 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 RESPATH_D3D "Software\\Microsoft\\Direct3D" void InformDriverFreeAGP(HANDLE hDD); void InformDriverToDeferFrees(HANDLE hDD); void InformDriverAGPWorkaroundAware(HANDLE hDD); #ifdef DEBUG // Debug helper to indicate which surfaces are around // void DebugPrintSurfaceInfo(PDDSURFHANDLE pSurf) { 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; } } // DebugPrintSurfaceInfo #endif 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 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) { D3DADAPTER_IDENTIFIER8 DI; GetAdapterInfo(pDevice->szDeviceName, &DI, TRUE, TRUE, FALSE); pDevice->PCIID = (DI.VendorId << 16) | DI.DeviceId; pDevice->DriverVersionHigh = DI.DriverVersion.HighPart; pDevice->DriverVersionLow = DI.DriverVersion.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 FormatCompatibleWithDisplayFormat( PDDDEVICEHANDLE pDD, D3DFORMAT Format) { // The surface is compatible if formats match if (Format == pDD->DisplayFormatWithAlpha) return TRUE; return FALSE; } #undef DPF_MODNAME #define DPF_MODNAME "ReleaseDX7SurfaceHandle" void ReleaseDX7SurfaceHandle(HANDLE hDD, DWORD handle) { PDDDEVICEHANDLE pDeviceHandle = (PDDDEVICEHANDLE) hDD; pDeviceHandle->SurfaceHandleList.dwList[handle].nextentry = pDeviceHandle->SurfaceHandleList.dwFreeList; pDeviceHandle->SurfaceHandleList.dwFreeList = handle; } #undef DPF_MODNAME #define DPF_MODNAME "FreeSurfaceObject" void FreeSurfaceObject (PDDSURFHANDLE pSurf) { DWORD dwRet = DDHAL_DRIVER_NOTHANDLED; // If the surface was created by a software driver, we need to call the // software driver to destroy it. if (IS_SOFTWARE_DRIVER_SURFACE(pSurf)) { // In a creation failure case, we may have not actually called the // driver/kernel to create this surface yet. // Release the kernel's handle first so that it // can finish up whatever it wants to before we free // the underlying memory if (pSurf->hSurface != 0) { OsThunkDdDeleteSurfaceObject(pSurf->hSurface); } // Now free the SW driver's object if (pSurf->dwFlags & DDSURF_CREATECOMPLETE) { dwRet = SwDDIDestroySurface (pSurf->pDevice, pSurf); } } else if (pSurf->hSurface != 0) { if (pSurf->Pool != D3DPOOL_SYSTEMMEM) { if ((pSurf->Type == D3DRTYPE_COMMANDBUFFER) || (pSurf->Type == D3DRTYPE_VERTEXBUFFER) || (pSurf->Type == D3DRTYPE_INDEXBUFFER) ) { OsThunkDdDestroyD3DBuffer(pSurf->hSurface); } else { OsThunkDdDestroySurface(pSurf->hSurface, TRUE); } } OsThunkDdDeleteSurfaceObject(pSurf->hSurface); pSurf->hSurface = NULL; } if (pSurf->dwCookie) { // If CreateSurfaceEx was called on a sysmem surface, we need to tell // the driver. On NT, we only need to tell the software driver since // the kernel handles this for a real driver. if ((IS_SOFTWARE_DRIVER(pSurf->pDevice)) && (pSurf->dwFlags & DDSURF_CREATECOMPLETE) && (pSurf->Pool == D3DPOOL_SYSTEMMEM)) { // DX7 called CreateSurfaceEx fpVidMem = 0 on each mipmap level // (even though it only creates it on the topmost level), so we // need to do the same to maintain driver compatibility. pSurf->pLcl->lpGbl->fpVidMem = 0; SwDDICreateSurfaceEx (pSurf->pDevice->pDD, pSurf->pLcl); } ReleaseDX7SurfaceHandle(pSurf->pDevice, pSurf->dwCookie); pSurf->dwCookie = 0; } if (pSurf->pLcl != NULL) { MemFree(pSurf->pLcl); pSurf->pLcl = NULL; } } #undef DPF_MODNAME #define DPF_MODNAME "CheckForDeviceLost" BOOL CheckForDeviceLost (HANDLE hDD) { PDDDEVICEHANDLE pDeviceHandle = (PDDDEVICEHANDLE) hDD; PDDSURFHANDLE pSurf; DWORD Uniqueness = DdQueryDisplaySettingsUniqueness(); if (!pDeviceHandle->bDeviceLost && (Uniqueness != pDeviceHandle->DisplayUniqueness)) { // If this is the first device to notice it is lost, then set // some state. if (InterlockedCompareExchange(&GlobalUniqueness, Uniqueness, GlobalUniqueness) != Uniqueness) { NumReadyDevices = 0; } pDeviceHandle->dwFlags &= ~DDDEVICE_READY; // The device has transitioned to the lost state, so we need // walk through the list and free the vidmem surfaces.. pDeviceHandle->bDeviceLost = TRUE; pSurf = pDeviceHandle->pSurfList; while (pSurf != NULL) { if (IS_SURFACE_LOOSABLE(pSurf)) { if (pSurf->LockRefCnt == 0) { FreeSurfaceObject(pSurf); } pSurf->fpVidMem = (ULONG_PTR) NULL; } pSurf = pSurf->pNext; } } return pDeviceHandle->bDeviceLost; } #undef DPF_MODNAME #define DPF_MODNAME "GetDX7SurfaceHandle" 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(). Can't create new texture/surface/buffer."); 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(). Can't create new texture/surface/buffer"); 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; } /*****************************Private*Routine******************************\ * DdConvertToOldFormat * * History: * 3-Nov-1999 -by- Scott MacDonald [smac] * Wrote it. \**************************************************************************/ #undef DPF_MODNAME #define DPF_MODNAME "ConvertToOldFormat" 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******************************\ * InitSurfaceStructures * * History: * 06-Dec-1999 -by- Scott MacDonald [smac] * Wrote it. \**************************************************************************/ #undef DPF_MODNAME #define DPF_MODNAME "InitSurfaceStructure" void InitSurfaceStructures( PD3D8_CREATESURFACEDATA pCreateSurface, DD_SURFACE_LOCAL* pDDSurfaceLocal, DD_SURFACE_GLOBAL* pDDSurfaceGlobal, DD_SURFACE_MORE* pDDSurfaceMore ) { PDDDEVICEHANDLE pDevice = (PDDDEVICEHANDLE) pCreateSurface->hDD; DWORD i; DWORD j; DWORD dwBit; for (i = 0; i < pCreateSurface->dwSCnt; i++) { // Make sure there's always a valid pixel format for the surface: if ((pCreateSurface->Format != D3DFMT_UNKNOWN) && (pCreateSurface->Format != D3DFMT_VERTEXDATA) && (pCreateSurface->Format != D3DFMT_INDEX16) && (pCreateSurface->Format != D3DFMT_INDEX32)) { pDDSurfaceLocal[i].dwFlags |= DDRAWISURF_HASPIXELFORMAT; // 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)) { ConvertToOldFormat(&pDDSurfaceGlobal[i].ddpfSurface, pDevice->DisplayFormatWithAlpha); } else { ConvertToOldFormat(&pDDSurfaceGlobal[i].ddpfSurface, (D3DFORMAT)pCreateSurface->Format); } } // Setup width/height first pDDSurfaceGlobal[i].wWidth = pCreateSurface->pSList[i].cpWidth; pDDSurfaceGlobal[i].wHeight = pCreateSurface->pSList[i].cpHeight; //dwCaps3==1 means 1 sample per pixel. pDDSurfaceMore[i].ddsCapsEx.dwCaps3 = DDSCAPS3_MULTISAMPLE_MASK & (DWORD) pCreateSurface->MultiSampleType; if (pCreateSurface->dwUsage & D3DUSAGE_ALPHACHANNEL) { pDDSurfaceMore[i].ddsCapsEx.dwCaps2 |= DDSCAPS2_ENABLEALPHACHANNEL; } switch (pCreateSurface->Type) { case D3DRTYPE_SURFACE: // Surfaces come in three general flavors: // - Primary flip chains // - Z buffers // - OffscreenPlain (RenderTargets or just sys-mem stuff) // // Textures are a different resource type 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) { pDDSurfaceLocal[i].ddsCaps.dwCaps |= DDSCAPS_PRIMARYSURFACE; } else { if (i == 0) { // This is the front buffer pDDSurfaceLocal[i].ddsCaps.dwCaps |= DDSCAPS_PRIMARYSURFACE | DDSCAPS_VISIBLE | DDSCAPS_FRONTBUFFER; } else { // This is a back buffer pDDSurfaceLocal[i].ddsCaps.dwCaps |= DDSCAPS_BACKBUFFER; } // All surfaces in the primary chain get these caps pDDSurfaceLocal[i].ddsCaps.dwCaps |= DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_3DDEVICE; // We also get a CreateEx handle for all surfaces in the // chain, but not if we're running w/ a software driver. if (((PDDDEVICEHANDLE)pCreateSurface->hDD)->pDD == NULL) { pDDSurfaceMore[i].dwSurfaceHandle = GetDX7SurfaceHandle(pCreateSurface->hDD); } } } else if (pCreateSurface->dwUsage & D3DUSAGE_DEPTHSTENCIL) { DDASSERT(0 == (pCreateSurface->dwUsage & D3DUSAGE_DISCARD) ); pDDSurfaceLocal[i].ddsCaps.dwCaps |= DDSCAPS_ZBUFFER; pDDSurfaceMore[i].dwSurfaceHandle = GetDX7SurfaceHandle(pCreateSurface->hDD); } else { pDDSurfaceLocal[i].ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN; } break; case D3DRTYPE_VOLUME: // We don't create stand-alone volumes DDASSERT(FALSE); break; case D3DRTYPE_TEXTURE: DDASSERT(0 == (pCreateSurface->dwUsage & D3DUSAGE_DISCARD) ); pDDSurfaceLocal[i].ddsCaps.dwCaps |= DDSCAPS_TEXTURE; //mipmaps are only DDI-level mipmaps if they're more than one level if (pCreateSurface->dwSCnt>1) pDDSurfaceLocal[i].ddsCaps.dwCaps |= DDSCAPS_MIPMAP; if (i > 0) { // Mark non-top levels as being a sub-level pDDSurfaceMore[i].ddsCapsEx.dwCaps2 |= DDSCAPS2_MIPMAPSUBLEVEL; } if (pCreateSurface->dwUsage & D3DUSAGE_DYNAMIC) { pDDSurfaceMore[i].ddsCapsEx.dwCaps2 |= DDSCAPS2_HINTDYNAMIC; } pDDSurfaceMore[i].dwSurfaceHandle = GetDX7SurfaceHandle(pCreateSurface->hDD); break; case D3DRTYPE_VOLUMETEXTURE: DDASSERT(0 == (pCreateSurface->dwUsage & D3DUSAGE_DISCARD) ); pDDSurfaceLocal[i].ddsCaps.dwCaps |= DDSCAPS_TEXTURE | DDSCAPS_MIPMAP; pDDSurfaceMore[i].ddsCapsEx.dwCaps2 |= DDSCAPS2_VOLUME; pDDSurfaceMore[i].ddsCapsEx.dwCaps4 = MAKELONG((WORD)(pCreateSurface->pSList[i].cpDepth),0); if (i > 0) { // Mark non-top levels as being a sub-level pDDSurfaceMore[i].ddsCapsEx.dwCaps2 |= DDSCAPS2_MIPMAPSUBLEVEL; } if (pCreateSurface->dwUsage & D3DUSAGE_DYNAMIC) { pDDSurfaceMore[i].ddsCapsEx.dwCaps2 |= DDSCAPS2_HINTDYNAMIC; } pDDSurfaceMore[i].dwSurfaceHandle = GetDX7SurfaceHandle(pCreateSurface->hDD); break; case D3DRTYPE_CUBETEXTURE: DDASSERT(0 == (pCreateSurface->dwUsage & D3DUSAGE_DISCARD) ); pDDSurfaceLocal[i].ddsCaps.dwCaps |= DDSCAPS_TEXTURE | DDSCAPS_COMPLEX; pDDSurfaceMore[i].ddsCapsEx.dwCaps2 |= DDSCAPS2_CUBEMAP; pDDSurfaceMore[i].dwSurfaceHandle = GetDX7SurfaceHandle(pCreateSurface->hDD); //cubemaps are only DDI-level mipmaps if they're more than one level if (pCreateSurface->dwSCnt>6) pDDSurfaceLocal[i].ddsCaps.dwCaps |= DDSCAPS_MIPMAP; // DX8 only supports creation of all faces { DWORD dwOrderedFaces[6] = { DDSCAPS2_CUBEMAP_POSITIVEX, DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY, DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ }; int MipLevels; 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. pDDSurfaceMore[i].ddsCapsEx.dwCaps2 |= dwOrderedFaces[i/MipLevels]; //every MipLevels'th surface is a top-level face, if (i % MipLevels) { // Mark non-top levels as being a sub-level pDDSurfaceMore[i].ddsCapsEx.dwCaps2 |= DDSCAPS2_MIPMAPSUBLEVEL; } if (pCreateSurface->dwUsage & D3DUSAGE_DYNAMIC) { pDDSurfaceMore[i].ddsCapsEx.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. pDDSurfaceLocal[i].ddsCaps.dwCaps |= DDSCAPS_TEXTURE; break; case D3DRTYPE_COMMANDBUFFER: DDASSERT(0 == (pCreateSurface->dwUsage & D3DUSAGE_DISCARD) ); pDDSurfaceLocal[i].ddsCaps.dwCaps |= DDSCAPS_EXECUTEBUFFER; pDDSurfaceMore[i].dwSurfaceHandle = GetDX7SurfaceHandle(pCreateSurface->hDD); DDASSERT((pCreateSurface->dwUsage & D3DUSAGE_INTERNALBUFFER) == 0); pDDSurfaceMore[i].ddsCapsEx.dwCaps2 |= DDSCAPS2_COMMANDBUFFER; pDDSurfaceGlobal[i].dwLinearSize = pDDSurfaceGlobal[i].wWidth; break; case D3DRTYPE_VERTEXBUFFER: DDASSERT(0 == (pCreateSurface->dwUsage & D3DUSAGE_DISCARD) ); pDDSurfaceLocal[i].ddsCaps.dwCaps |= DDSCAPS_EXECUTEBUFFER; if (!(pCreateSurface->dwUsage & D3DUSAGE_INTERNALBUFFER)) { pDDSurfaceMore[i].ddsCapsEx.dwCaps2 |= DDSCAPS2_VERTEXBUFFER; } if (pDevice->DriverLevel >= 8) { if (pCreateSurface->dwUsage & D3DUSAGE_DYNAMIC) { pDDSurfaceMore[i].ddsCapsEx.dwCaps2 |= DDSCAPS2_HINTDYNAMIC; } else { pDDSurfaceMore[i].ddsCapsEx.dwCaps2 |= DDSCAPS2_HINTSTATIC; } } pDDSurfaceMore[i].dwSurfaceHandle = GetDX7SurfaceHandle(pCreateSurface->hDD); pDDSurfaceGlobal[i].dwLinearSize = pDDSurfaceGlobal[i].wWidth; break; case D3DRTYPE_INDEXBUFFER: DDASSERT(0 == (pCreateSurface->dwUsage & D3DUSAGE_DISCARD) ); pDDSurfaceLocal[i].ddsCaps.dwCaps |= DDSCAPS_EXECUTEBUFFER; pDDSurfaceMore[i].ddsCapsEx.dwCaps2 |= DDSCAPS2_INDEXBUFFER; if (pDevice->DriverLevel >= 8) { if (pCreateSurface->dwUsage & D3DUSAGE_DYNAMIC) { pDDSurfaceMore[i].ddsCapsEx.dwCaps2 |= DDSCAPS2_HINTDYNAMIC; } else { pDDSurfaceMore[i].ddsCapsEx.dwCaps2 |= DDSCAPS2_HINTSTATIC; } } pDDSurfaceMore[i].dwSurfaceHandle = GetDX7SurfaceHandle(pCreateSurface->hDD); pDDSurfaceGlobal[i].dwLinearSize = pDDSurfaceGlobal[i].wWidth; break; } if (pCreateSurface->dwUsage & D3DUSAGE_RENDERTARGET) { pDDSurfaceLocal[i].ddsCaps.dwCaps |= DDSCAPS_3DDEVICE; if (pDDSurfaceMore[i].dwSurfaceHandle == 0) { pDDSurfaceMore[i].dwSurfaceHandle = GetDX7SurfaceHandle(pCreateSurface->hDD); } } if (pCreateSurface->dwUsage & D3DUSAGE_DEPTHSTENCIL) { pDDSurfaceLocal[i].ddsCaps.dwCaps |= DDSCAPS_ZBUFFER; } if (pDevice->DriverLevel >= 8) { if (pCreateSurface->dwUsage & D3DUSAGE_LOADONCE) { pDDSurfaceMore[i].ddsCapsEx.dwCaps2 |= DDSCAPS2_OPAQUE; } if (pCreateSurface->dwUsage & D3DUSAGE_WRITEONLY) { pDDSurfaceLocal[i].ddsCaps.dwCaps |= DDSCAPS_WRITEONLY; } if (!(pCreateSurface->dwUsage & D3DUSAGE_LOCK) && !(pCreateSurface->dwUsage & D3DUSAGE_LOADONCE)) { pDDSurfaceMore[i].ddsCapsEx.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); pDDSurfaceMore[i].ddsCapsEx.dwCaps2 |= DDSCAPS2_DISCARDBACKBUFFER; } if (pCreateSurface->dwUsage & D3DUSAGE_POINTS) { pDDSurfaceMore[i].ddsCapsEx.dwCaps2 |= DDSCAPS2_POINTS; } if (pCreateSurface->dwUsage & D3DUSAGE_RTPATCHES) { pDDSurfaceMore[i].ddsCapsEx.dwCaps2 |= DDSCAPS2_RTPATCHES; } if (pCreateSurface->dwUsage & D3DUSAGE_NPATCHES) { pDDSurfaceMore[i].ddsCapsEx.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) { if (pCreateSurface->dwUsage & D3DUSAGE_LOADONCE) { pDDSurfaceMore[i].ddsCapsEx.dwCaps2 |= DDSCAPS2_OPAQUE; } } // We allow WRITEONLY through only for VBs if (pCreateSurface->Type == D3DRTYPE_VERTEXBUFFER) { if (pCreateSurface->dwUsage & D3DUSAGE_WRITEONLY) { pDDSurfaceLocal[i].ddsCaps.dwCaps |= DDSCAPS_WRITEONLY; } } } switch (pCreateSurface->Pool) { case D3DPOOL_LOCALVIDMEM: pDDSurfaceLocal[i].ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY; break; case D3DPOOL_NONLOCALVIDMEM: pDDSurfaceLocal[i].ddsCaps.dwCaps |= DDSCAPS_NONLOCALVIDMEM | DDSCAPS_VIDEOMEMORY; break; case D3DPOOL_SYSTEMMEM: pDDSurfaceLocal[i].ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; break; case D3DPOOL_MANAGED: pDDSurfaceLocal[i].dwFlags |= DDRAWISURF_DRIVERMANAGED; pDDSurfaceLocal[i].ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY; pDDSurfaceMore[i].ddsCapsEx.dwCaps2 |= DDSCAPS2_TEXTUREMANAGE; break; case D3DPOOL_DEFAULT: pCreateSurface->Pool = D3DPOOL_LOCALVIDMEM; pDDSurfaceLocal[i].ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY; break; default: /* Unknown Pool?? */ DDASSERT(FALSE); break; } } } /*****************************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; } } /*****************************Private*Routine******************************\ * CreateVidMemSurface * * History: * 06-Dec-1999 -by- Scott MacDonald [smac] * Wrote it. \**************************************************************************/ #undef DPF_MODNAME #define DPF_MODNAME "CreateVidMemSurface" HRESULT CreateVidMemSurface( PD3D8_CREATESURFACEDATA pCreateSurface, DD_SURFACE_LOCAL* pDDSurfaceLocal, DD_SURFACE_GLOBAL* pDDSurfaceGlobal, DD_SURFACE_MORE* pDDSurfaceMore, HANDLE* phInSurface, HANDLE* phOutSurface, BOOL bIsLost ) { DDSURFACEDESC2 SurfaceDesc; DD_CREATESURFACEDATA CreateData7; DWORD i; DWORD j; BOOL bRet; DDSURFHANDLE* pSurf; DD_CANCREATESURFACEDATA CanCreateData; DEFERREDCREATE* pDefCreate; if (DDSCAPS_EXECUTEBUFFER & pDDSurfaceLocal[0].ddsCaps.dwCaps) { if (!(DDDEVICE_SUPPORTD3DBUF & ((PDDDEVICEHANDLE)pCreateSurface->hDD)->dwFlags) ) { return E_FAIL; } } // If the device is lost, we don't want to allocate vidmem or call the // kernel at this point (the surface will be released soon anyway). if (bIsLost) { DeviceLost: DDASSERT(pCreateSurface->bReUse == FALSE); for (i = 0; i < pCreateSurface->dwSCnt; i++) { pSurf = (PDDSURFHANDLE) pCreateSurface->pSList[i].hKernelHandle; pDDSurfaceMore[i].dwSurfaceHandle = 0; // There is a chance that the app may call Lock at some point, // in which case we have to allocate a buffer that they can write // to. Allocating the buffer now is a bit wasteful, but if we // allocate it at Lock time the allocation may fail and I'm // guessing that apps will handle create surface failures better // than they will Lock failures, so we will do the allocation now. pDDSurfaceGlobal[i].lPitch = pCreateSurface->pSList[i].cpWidth * 8; pDDSurfaceGlobal[i].dwLinearSize = pDDSurfaceGlobal[i].lPitch; if ((pCreateSurface->Type == D3DRTYPE_VOLUME) || (pCreateSurface->Type == D3DRTYPE_VOLUMETEXTURE)) { pSurf->lSlicePitch = pDDSurfaceGlobal[i].lPitch * pCreateSurface->pSList[i].cpHeight; pDDSurfaceGlobal[i].fpVidMem = (ULONG_PTR) MemAlloc(pSurf->lSlicePitch * pCreateSurface->pSList[i].cpDepth); } else { pDDSurfaceGlobal[i].fpVidMem = (ULONG_PTR) MemAlloc(pDDSurfaceGlobal[i].lPitch * pCreateSurface->pSList[i].cpHeight); } if (pDDSurfaceGlobal[i].fpVidMem == (ULONG_PTR) NULL) { for (j = 0; j < i; j++) { MemFree((void*)pDDSurfaceGlobal[j].fpVidMem); } return E_OUTOFMEMORY; } pSurf->dwFlags |= DDSURF_SYSMEMALLOCATED; } // If the surface is driver managed, we save the creation info so that // we can retry the creation at reset time if (pDDSurfaceLocal[0].dwFlags & DDRAWISURF_DRIVERMANAGED) { pDefCreate = (PDEFERREDCREATE)MemAlloc(sizeof(DEFERREDCREATE)); if (pDefCreate == NULL) { // Cleanup stuff that we allocated above for (i = 0; i < pCreateSurface->dwSCnt; ++i) { MemFree((void*)pDDSurfaceGlobal[i].fpVidMem); pSurf = (PDDSURFHANDLE) pCreateSurface->pSList[i].hKernelHandle; pSurf->dwFlags &= ~DDSURF_SYSMEMALLOCATED; } return E_OUTOFMEMORY; } // 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) { MemFree((void*)pDDSurfaceGlobal[i].fpVidMem); pSurf = (PDDSURFHANDLE) pCreateSurface->pSList[i].hKernelHandle; pSurf->dwFlags &= ~DDSURF_SYSMEMALLOCATED; } return E_OUTOFMEMORY; } // Copy CopyMemory(pDefCreate->CreateData.pSList, pCreateSurface->pSList, sizeof(DDSURFACEINFO) * pCreateSurface->dwSCnt); // Linkup pDefCreate->pNext = ((PDDDEVICEHANDLE)pCreateSurface->hDD)->pDeferList; ((PDDDEVICEHANDLE)pCreateSurface->hDD)->pDeferList = pDefCreate; // We need to release the cookies allocated in InitSurfaceStructures // because this is not an actual create. When we do the actual create, we // will be reallocating the cookies. for (i = 0; i < pCreateSurface->dwSCnt; ++i) { pSurf = (PDDSURFHANDLE) pCreateSurface->pSList[i].hKernelHandle; DDASSERT(pSurf->dwCookie != 0); ReleaseDX7SurfaceHandle(pSurf->pDevice, pSurf->dwCookie); pSurf->dwCookie = 0; } // *************************MEMORY LEAK WARNING*********************** // // The DEFERREDCREATE and DDSURFACEINFO allocations above will // not be cleaned up immediately if for some reason DdCreateSurface // (ie the caller of this function) fails after this function returns // success. As of 3/2001, DdCreateSurface has no code path that can // fail after we return ok below. // ******************************************************************* // } return S_OK; } // First setup the surface desc RtlZeroMemory(&SurfaceDesc, sizeof(SurfaceDesc)); SurfaceDesc.dwSize = sizeof(SurfaceDesc); SurfaceDesc.ddsCaps.dwCaps = pDDSurfaceLocal[0].ddsCaps.dwCaps; SurfaceDesc.ddsCaps.dwCaps2 = pDDSurfaceMore[0].ddsCapsEx.dwCaps2; SurfaceDesc.ddsCaps.dwCaps3 = pDDSurfaceMore[0].ddsCapsEx.dwCaps3; SurfaceDesc.ddsCaps.dwCaps4 = pDDSurfaceMore[0].ddsCapsEx.dwCaps4; SurfaceDesc.ddpfPixelFormat = pDDSurfaceGlobal[0].ddpfSurface; if ((pCreateSurface->Type == D3DRTYPE_TEXTURE) || (pCreateSurface->Type == D3DRTYPE_VOLUMETEXTURE)) { SurfaceDesc.dwMipMapCount = pCreateSurface->dwSCnt; if (SurfaceDesc.dwMipMapCount) { SurfaceDesc.dwFlags |= DDSD_MIPMAPCOUNT; } } else if (pCreateSurface->Type == D3DRTYPE_CUBETEXTURE) { if (pCreateSurface->dwSCnt > 6) { SurfaceDesc.dwMipMapCount = pCreateSurface->dwSCnt / 6; SurfaceDesc.dwFlags |= DDSD_MIPMAPCOUNT; } } else if (pCreateSurface->dwSCnt > 1) { SurfaceDesc.dwBackBufferCount = pCreateSurface->dwSCnt - 1; SurfaceDesc.dwFlags |= DDSD_BACKBUFFERCOUNT; } SurfaceDesc.dwHeight = pDDSurfaceGlobal[0].wHeight; SurfaceDesc.dwWidth = pDDSurfaceGlobal[0].wWidth; SurfaceDesc.dwFlags |= DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; if (pDDSurfaceLocal[0].dwFlags & DDRAWISURF_HASPIXELFORMAT) { SurfaceDesc.dwFlags |= DDSD_PIXELFORMAT; } if (pCreateSurface->Type == D3DRTYPE_VERTEXBUFFER) { SurfaceDesc.dwFVF = pCreateSurface->dwFVF; SurfaceDesc.dwFlags |= DDSD_FVF; } if (SurfaceDesc.ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER) { SurfaceDesc.dwLinearSize = pCreateSurface->pSList[0].iPitch; SurfaceDesc.dwFlags |= DDSD_LINEARSIZE; } if (SurfaceDesc.ddsCaps.dwCaps2 & DDSCAPS2_VOLUME) { SurfaceDesc.dwDepth = pCreateSurface->pSList[0].cpDepth; SurfaceDesc.dwFlags |= DDSD_DEPTH; } if (SurfaceDesc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER) { // ATI Rage3 driver in Win2K still expects dwZbufferBitDepth // in the old place in DDSD, so put it there but probably not // set the bit in dwFlags as we don't advocate it. ((DDSURFACEDESC*)&SurfaceDesc)->dwZBufferBitDepth = SurfaceDesc.ddpfPixelFormat.dwZBufferBitDepth; } // We do not support texture stage in DX8 DDASSERT((SurfaceDesc.dwFlags & DDSD_TEXTURESTAGE) == 0); DDASSERT(SurfaceDesc.dwTextureStage == 0); // Now call CanCreateSurface since this is where most drivers do the // majority of their caps checking. RtlZeroMemory(&CanCreateData, sizeof(CanCreateData)); CanCreateData.lpDDSurfaceDesc = (DDSURFACEDESC*) &SurfaceDesc; if (!FormatCompatibleWithDisplayFormat(((PDDDEVICEHANDLE)pCreateSurface->hDD), pCreateSurface->Format)) { CanCreateData.bIsDifferentPixelFormat = TRUE; } else { CanCreateData.bIsDifferentPixelFormat = FALSE; } if (SurfaceDesc.ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER) { bRet = OsThunkDdCanCreateD3DBuffer(DDHANDLE(pCreateSurface->hDD), &CanCreateData); } else { bRet = OsThunkDdCanCreateSurface(DDHANDLE(pCreateSurface->hDD), &CanCreateData); } if ( bRet ) { if (CanCreateData.ddRVal != S_OK) { if (CanCreateData.ddRVal == DDERR_SURFACELOST) { if (!pCreateSurface->bReUse) { goto DeviceLost; } } return CanCreateData.ddRVal; } } /* * if the driver didn't handle it, then fail any requests to create a * surface that differs in format from the primary surface, except for * z buffer and alpha */ else { // On Win2K, due to broken kernel, when the device is lost, the kernel // returns DDHAL_DRIVER_NOT_HANDLED and the return code is DDERR_GENERIC. // When we detect this, we check for device lost ourselves. if (CanCreateData.ddRVal == DDERR_GENERIC && CheckForDeviceLost (pCreateSurface->hDD)) { if (!pCreateSurface->bReUse) { goto DeviceLost; } return DDERR_SURFACELOST; } if (!FormatCompatibleWithDisplayFormat(((PDDDEVICEHANDLE)pCreateSurface->hDD), pCreateSurface->Format) && !(SurfaceDesc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER|DDSCAPS_ALPHA|DDSCAPS_EXECUTEBUFFER)) ) { return DDERR_INVALIDPIXELFORMAT; } } // Calculate the surface pitch. The driver may override this, but if we // don't initialize it and the driver doesn't explicitly specify it, then // the kernel may fail the allocation. if (!(SurfaceDesc.ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER)) { for (i = 0; i < pCreateSurface->dwSCnt; i++) { if (SurfaceDesc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) { pDDSurfaceGlobal[i].lPitch = ((PDDDEVICEHANDLE)pCreateSurface->hDD)->DisplayPitch; } else if ((pDDSurfaceLocal[0].dwFlags & DDRAWISURF_HASPIXELFORMAT) && (pDDSurfaceGlobal[0].ddpfSurface.dwRGBBitCount > 0)) { pDDSurfaceGlobal[i].lPitch = (pDDSurfaceGlobal[0].ddpfSurface.dwRGBBitCount / 8) * pDDSurfaceGlobal[i].wWidth; // Assume that they need to be 8 byte aligned. pDDSurfaceGlobal[i].lPitch += 7; pDDSurfaceGlobal[i].lPitch &= 0xfffffff8; } } } // If the surface requires attachments, we need to set that up before the // CreateSurface call. if (pCreateSurface->dwSCnt > 1) { // First, create all of the surface objects for (i = 0; i < pCreateSurface->dwSCnt; i++) { phInSurface[i] = OsThunkDdCreateSurfaceObject(DDHANDLE(pCreateSurface->hDD), NULL, &pDDSurfaceLocal[i], &pDDSurfaceMore[i], &pDDSurfaceGlobal[i], FALSE); if (phInSurface[i] == NULL) { for (j = 0; j < i; j++) { OsThunkDdDeleteSurfaceObject(phInSurface[j]); } // Looks like we are lost or something. Check it out. if (CheckForDeviceLost (pCreateSurface->hDD)) { if (!pCreateSurface->bReUse) { goto DeviceLost; } return DDERR_SURFACELOST; } return E_FAIL; } } // Now attach them all for (i = 1; i < pCreateSurface->dwSCnt; i++) { bRet = OsThunkDdAttachSurface(phInSurface[SelectAttachmentSurface(pCreateSurface,i)], phInSurface[i]); // smac: handle error condition } // If it's the primary surface chain, I also need to attach the back // to the front (to avoid potential compatibility issues). if (pDDSurfaceLocal[0].ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) { bRet = OsThunkDdAttachSurface(phInSurface[pCreateSurface->dwSCnt - 1], phInSurface[0]); } } // Preset an error in case the kernel can't write status // back for some reason. CreateData7.ddRVal = E_FAIL; CreateData7.dwSCnt = pCreateSurface->dwSCnt; if (SurfaceDesc.ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER) { bRet = OsThunkDdCreateD3DBuffer(DDHANDLE(pCreateSurface->hDD), phInSurface, (LPDDSURFACEDESC)&SurfaceDesc, pDDSurfaceGlobal, pDDSurfaceLocal, pDDSurfaceMore, (PDD_CREATESURFACEDATA) &CreateData7, phOutSurface); } else { bRet = OsThunkDdCreateSurface(DDHANDLE(pCreateSurface->hDD), phInSurface, (LPDDSURFACEDESC)&SurfaceDesc, pDDSurfaceGlobal, pDDSurfaceLocal, pDDSurfaceMore, (PDD_CREATESURFACEDATA) &CreateData7, phOutSurface); } if ( bRet && (CreateData7.ddRVal != S_OK)) { if (pCreateSurface->dwSCnt > 1) { for (i = 0; i < pCreateSurface->dwSCnt; i++) { OsThunkDdDeleteSurfaceObject(phInSurface[i]); } } if (CreateData7.ddRVal == DDERR_SURFACELOST) { if (!pCreateSurface->bReUse) { goto DeviceLost; } } // Broken Win2K kernel fails with DDERR_OUTOFVIDEOMEMORY, so handle this case else if ((CreateData7.ddRVal == DDERR_OUTOFVIDEOMEMORY || CreateData7.ddRVal == DDERR_GENERIC) && CheckForDeviceLost (pCreateSurface->hDD)) { if (!pCreateSurface->bReUse) { goto DeviceLost; } CreateData7.ddRVal = DDERR_SURFACELOST; } return CreateData7.ddRVal; } if (pDDSurfaceLocal[0].ddsCaps.dwCaps & DDSCAPS_NONLOCALVIDMEM) { pCreateSurface->Pool = D3DPOOL_NONLOCALVIDMEM; for (i = 0; i < pCreateSurface->dwSCnt; i++) { pSurf = (PDDSURFHANDLE) pCreateSurface->pSList[i].hKernelHandle; pSurf->Pool = D3DPOOL_NONLOCALVIDMEM; } } for (i = 0; i < pCreateSurface->dwSCnt; i++) { pSurf = (PDDSURFHANDLE) pCreateSurface->pSList[i].hKernelHandle; pSurf->hSurface = phOutSurface[i]; } return CreateData7.ddRVal; } /*****************************Private*Routine******************************\ * CreateSysMemSurface * * History: * 06-Dec-1999 -by- Scott MacDonald [smac] * Wrote it. \**************************************************************************/ #undef DPF_MODNAME #define DPF_MODNAME "CreateSysMemSurface" HRESULT CreateSysMemSurface( PD3D8_CREATESURFACEDATA pCreateSurface, DD_SURFACE_LOCAL* pDDSurfaceLocal, DD_SURFACE_GLOBAL* pDDSurfaceGlobal, DD_SURFACE_MORE* pDDSurfaceMore, BOOL bIsLost ) { DWORD i; DWORD j; HRESULT hr; BOOL bRet; DDSURFHANDLE* pSurf; hr = S_OK; for (i = 0; i < pCreateSurface->dwSCnt; i++) { pDDSurfaceGlobal[i].fpVidMem = (ULONG_PTR)pCreateSurface->pSList[i].pbPixels; pDDSurfaceGlobal[i].lPitch = pCreateSurface->pSList[i].iPitch; if ((pCreateSurface->Type == D3DRTYPE_VOLUME) || (pCreateSurface->Type == D3DRTYPE_VOLUMETEXTURE)) { pDDSurfaceGlobal[i].dwBlockSizeY = pCreateSurface->pSList[i].iSlicePitch; } // Hack for NT; they don't support FourCC codes if (pDDSurfaceGlobal[i].ddpfSurface.dwFlags == DDPF_FOURCC) { if (pCreateSurface->Format == D3DFMT_UYVY || pCreateSurface->Format == D3DFMT_YUY2) { pDDSurfaceGlobal[i].ddpfSurface.dwRGBBitCount = 16; // lie about pitch pDDSurfaceGlobal[i].lPitch = ((pDDSurfaceGlobal[i].wWidth*2 + 7) & ~7); } else if (pCreateSurface->Format == D3DFMT_DXT1 || pCreateSurface->Format == D3DFMT_DXT2 || pCreateSurface->Format == D3DFMT_DXT3 || pCreateSurface->Format == D3DFMT_DXT4 || pCreateSurface->Format == D3DFMT_DXT5) { DWORD blksize; DWORD realwidth = pDDSurfaceGlobal[i].wWidth; DWORD realheight = pDDSurfaceGlobal[i].wHeight; WORD dx, dy; if (pCreateSurface->Format == D3DFMT_DXT1) { blksize = 8; } else { blksize = 16; } // HACK STOLEN FROM DX7 DDHEL // used the same logic as dx7 to avoid compat pain // The NT bug won't let us create this surface unless we lie. // We have to make up a width, height, pitch, and pixel size // that GDI will accept as valid. dx = (WORD)((realwidth + 3) >> 2); // number of 4x4 blocks in a row dy = (WORD)((realheight + 3) >> 2); // number of 4x4 blocks in a column pDDSurfaceGlobal[i].wHeight = dy; // lie about height pDDSurfaceGlobal[i].lPitch = dx*blksize; // lie about pitch pDDSurfaceGlobal[i].wWidth = (WORD)pDDSurfaceGlobal[i].lPitch; // lie about width pDDSurfaceGlobal[i].ddpfSurface.dwRGBBitCount = 8; // lie about pixel size } } // The presence of a software driver can make a sysmem surface act // like a vidmem surface, so we need to explicitly say that it's in sysmem pDDSurfaceLocal[i].ddsCaps.dwCaps &= ~(DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_NONLOCALVIDMEM); pDDSurfaceLocal[i].ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; pSurf = (PDDSURFHANDLE) pCreateSurface->pSList[i].hKernelHandle; pSurf->hSurface = OsThunkDdCreateSurfaceObject(DDHANDLE(pCreateSurface->hDD), NULL, &pDDSurfaceLocal[i], &pDDSurfaceMore[i], &pDDSurfaceGlobal[i], TRUE); if (pSurf->hSurface == NULL) { // Note that the main reason for this error is actually // out-of-memory; but it could also point at a bug // somewhere between the validation logic in kernel // and the validation logic in our runtime, DPF_ERR("Kernel failed registration of sys-mem object; out of system-memory condition"); hr = E_OUTOFMEMORY; } } // If we successfully created the handles, then we create any attachments // that we might require. if (SUCCEEDED(hr)) { for (i = 1; i < pCreateSurface->dwSCnt; i++) { pSurf = (PDDSURFHANDLE) pCreateSurface->pSList[i].hKernelHandle; bRet = OsThunkDdAttachSurface( ((PDDSURFHANDLE)pCreateSurface->pSList[ SelectAttachmentSurface(pCreateSurface,i) ].hKernelHandle)->hSurface, pSurf->hSurface); // smac: handle error condition } } // If we're still OK, then we should call CreateSurfaceEx if (SUCCEEDED(hr)) { if (pDDSurfaceMore[0].dwSurfaceHandle != 0) { // If using a software driver, we need to call CreateSurfaceEx // in the software driver; otherwsie, we call the kernel if (!IS_SOFTWARE_DRIVER(pCreateSurface->hDD)) { if (bIsLost) { // We set defer on the top level so CreateSurfaceEx gets called on Reset pSurf = (PDDSURFHANDLE) pCreateSurface->pSList[0].hKernelHandle; pSurf->dwFlags |= DDSURF_DEFERCREATEEX; return hr; } hr = OsThunkDdCreateSurfaceEx( DDHANDLE(pCreateSurface->hDD), ((PDDSURFHANDLE)pCreateSurface->pSList[0].hKernelHandle)->hSurface, pDDSurfaceMore[0].dwSurfaceHandle); if (FAILED(hr)) { if (hr == DDERR_SURFACELOST || CheckForDeviceLost (pCreateSurface->hDD)) // Due to broken Win2K implementation { // We set defer on the top level so CreateSurfaceEx gets called on Reset pSurf = (PDDSURFHANDLE) pCreateSurface->pSList[0].hKernelHandle; pSurf->dwFlags |= DDSURF_DEFERCREATEEX; return S_OK; } } } } } return hr; } BOOL IsWhistler() { OSVERSIONINFOEX osvi; DWORDLONG dwlConditionMask = 0; ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); osvi.dwMajorVersion = 5; osvi.dwMinorVersion = 1; VER_SET_CONDITION( dwlConditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL ); VER_SET_CONDITION( dwlConditionMask, VER_MINORVERSION, VER_GREATER_EQUAL ); return VerifyVersionInfo(&osvi, VER_MAJORVERSION|VER_MINORVERSION, dwlConditionMask); } // ResetUniqueness will cause runtime to think there is a device lost, // have to do that only for whistler when fscreen app alt-tab away to // desktop mode that is the same as the fullscreen, whistler void ResetUniqueness( HANDLE hDD ) { PDDDEVICEHANDLE pDeviceHandle = (PDDDEVICEHANDLE) hDD; if (pDeviceHandle->bIsWhistler) pDeviceHandle->DisplayUniqueness = 0; } /*****************************Private*Routine******************************\ * DdCreateSurface * * History: * 2-Nov-1999 -by- Scott MacDonald [smac] * Wrote it. \**************************************************************************/ #undef DPF_MODNAME #define DPF_MODNAME "DdCreateSurface" HRESULT APIENTRY DdCreateSurface( PD3D8_CREATESURFACEDATA pCreateSurface ) { ULONG i; ULONG j; DDSURFACEDESC2 SurfaceDesc; HANDLE hInSurface; HANDLE hOutSurface; DD_SURFACE_LOCAL SurfaceLocal; DD_SURFACE_GLOBAL SurfaceGlobal; DD_SURFACE_MORE SurfaceMore; DD_SURFACE_LOCAL* pDDSurfaceLocal = NULL; DD_SURFACE_GLOBAL* pDDSurfaceGlobal = NULL; DD_SURFACE_MORE* pDDSurfaceMore = NULL; HANDLE* phInSurface = NULL; HANDLE* phOutSurface = NULL; HRESULT hr; BOOL bSysMemCreate = FALSE; PDDSURFHANDLE pSurf; BOOL bIsLost = FALSE; DWORD dwNumToCreate; PDDDEVICEHANDLE pDevice = (PDDDEVICEHANDLE) pCreateSurface->hDD; dwNumToCreate = pCreateSurface->dwSCnt; // If the device is lost, we don't want to actually allocate vidmem, but // we still need to support sysmem surfaces. We also have to fake up // vidmem allocations since we only want to expose lost devices in a // couple of places. if (CheckForDeviceLost (pCreateSurface->hDD)) { bIsLost = TRUE; if (pCreateSurface->bReUse) { return DDERR_SURFACELOST; } } // For every surface, convert to the kernel's surface data structure, // call the kernel, then convert back: hr = S_OK; // If we are only creating one, no need to allocate gobs of memory; otherwise, do it if (dwNumToCreate == 1) { RtlZeroMemory(&SurfaceLocal, sizeof(SurfaceLocal)); RtlZeroMemory(&SurfaceGlobal, sizeof(SurfaceGlobal)); RtlZeroMemory(&SurfaceMore, sizeof(SurfaceMore)); hInSurface = NULL; hOutSurface = NULL; pDDSurfaceLocal = &SurfaceLocal; pDDSurfaceGlobal = &SurfaceGlobal; pDDSurfaceMore = &SurfaceMore; phInSurface = &hInSurface; phOutSurface = &hOutSurface; } else { pDDSurfaceLocal = (DD_SURFACE_LOCAL*) MemAlloc( sizeof(DD_SURFACE_LOCAL) * dwNumToCreate); pDDSurfaceGlobal = (DD_SURFACE_GLOBAL*) MemAlloc( sizeof(DD_SURFACE_GLOBAL) * dwNumToCreate); pDDSurfaceMore = (DD_SURFACE_MORE*) MemAlloc( sizeof(DD_SURFACE_MORE) * dwNumToCreate); phInSurface = (HANDLE*) MemAlloc(sizeof(HANDLE) * dwNumToCreate); phOutSurface = (HANDLE*) MemAlloc( sizeof(HANDLE) * dwNumToCreate); if ((pDDSurfaceLocal == NULL) || (pDDSurfaceGlobal == NULL) || (pDDSurfaceMore == NULL) || (phInSurface == NULL) || (phOutSurface == NULL)) { hr = E_OUTOFMEMORY; goto CleanupCreate; } } InitSurfaceStructures (pCreateSurface, pDDSurfaceLocal, pDDSurfaceGlobal, pDDSurfaceMore); // Allocate the internal surface structures for each surface in the chain // and initialize it if we are not reusing the surface if (!pCreateSurface->bReUse) { for (i = 0; i < dwNumToCreate; i++) { pSurf = (PDDSURFHANDLE) MemAlloc(sizeof(DDSURFHANDLE)); if (pSurf == NULL) { hr = E_OUTOFMEMORY; goto CleanupCreate; } pSurf->Pool = pCreateSurface->Pool; pSurf->Format = pCreateSurface->Format; pSurf->Type = pCreateSurface->Type; // This is sort of a hack to save space. For regular surfaces, we need // to know the height to handle the lost case, but for volume textures, // we really need to know the depth. To save space, we will re-use the // same variable. if ((pSurf->Type == D3DRTYPE_VOLUME) || (pSurf->Type == D3DRTYPE_VOLUMETEXTURE)) { pSurf->dwHeight = pCreateSurface->pSList[i].cpDepth; } else { pSurf->dwHeight = pCreateSurface->pSList[i].cpHeight; } pCreateSurface->pSList[i].hKernelHandle = (HANDLE) pSurf; pSurf->pDevice = (PDDDEVICEHANDLE) pCreateSurface->hDD; // You may find it wasteful that we assign handles to each mipmap level, // even though we only call CreateSurfaceEx on the topmost level. We need // to do this, however, since DX7 worked this way and it also call // CreateSurfaceEx fpVidMem = 0 at release time on each level of the mipmap. pSurf->dwCookie = pDDSurfaceMore[i].dwSurfaceHandle; // Now figure out if this is a sysmem surface, a software driver // surface, or a HAL surface. if (pSurf->Pool != D3DPOOL_SYSTEMMEM) { // 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 // USAGE_OFFSCREENPLAIN (which are used for the cursors) if (IS_SOFTWARE_DRIVER(pCreateSurface->hDD) && !(pCreateSurface->dwUsage & D3DUSAGE_PRIMARYSURFACE) && !(pCreateSurface->dwUsage & D3DUSAGE_OFFSCREENPLAIN)) { pSurf->dwFlags |= DDSURF_SOFTWARE; } else { pSurf->dwFlags |= DDSURF_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 |= DDSURF_TREATASVIDMEM; } // If a software driver will see this surface (either because it // will create it, or because it's a sysmem surface that will need // to handle CreateEx), we need to build a heavyweight surface structure. if (IS_SOFTWARE_DRIVER(pCreateSurface->hDD)) { if (!(pSurf->dwFlags & DDSURF_HAL) && (pSurf->dwCookie != 0)) { pSurf->pLcl = SwDDIBuildHeavyWeightSurface( pSurf->pDevice->pDD, pCreateSurface, &pDDSurfaceLocal[i], &pDDSurfaceGlobal[i], &pDDSurfaceMore[i], i); if (pSurf->pLcl == NULL) { hr = E_OUTOFMEMORY; goto CleanupCreate; } } } } } else // fill in the new cookie { for (i = 0; i < dwNumToCreate; i++) { pSurf = (PDDSURFHANDLE) pCreateSurface->pSList[i].hKernelHandle; DDASSERT(pSurf->dwCookie == 0); pSurf->dwCookie = pDDSurfaceMore[i].dwSurfaceHandle; } } // Now create the actual surfaces pSurf = (PDDSURFHANDLE) pCreateSurface->pSList[0].hKernelHandle; if (pSurf->Pool == D3DPOOL_SYSTEMMEM) { hr = CreateSysMemSurface( pCreateSurface, pDDSurfaceLocal, pDDSurfaceGlobal, pDDSurfaceMore, bIsLost); } else if (pSurf->dwFlags & DDSURF_SOFTWARE) { // Call the software rasterizer if it can handle it. // This allows them to allocate the memory, etc., but // we still need to call the kernel to create an object hr = SwDDICreateSurface(pCreateSurface, pDDSurfaceLocal, pDDSurfaceGlobal, pDDSurfaceMore); // We only need to get a kernel-handle // for back-buffers if (SUCCEEDED(hr) && (pCreateSurface->dwUsage & D3DUSAGE_BACKBUFFER)) { hr = CreateSysMemSurface(pCreateSurface, pDDSurfaceLocal, pDDSurfaceGlobal, pDDSurfaceMore, bIsLost); if (FAILED(hr)) { // we need to mark all the surfaces // as completely built so that // we free them correctly for (i = 0; i < dwNumToCreate; i++) { pSurf = (PDDSURFHANDLE) pCreateSurface->pSList[i].hKernelHandle; pSurf->dwFlags |= DDSURF_CREATECOMPLETE; } } } } else { hr = CreateVidMemSurface (pCreateSurface, pDDSurfaceLocal, pDDSurfaceGlobal, pDDSurfaceMore, phInSurface, phOutSurface, bIsLost); } if (FAILED(hr)) { goto CleanupCreate; } // Everything worked so far, so now we just need to finish up. for(i = 0; i < dwNumToCreate; i++) { pSurf = (PDDSURFHANDLE) pCreateSurface->pSList[i].hKernelHandle; pSurf->dwFlags |= DDSURF_CREATECOMPLETE; if (!(pSurf->dwFlags & DDSURF_HAL)) { // It's a sysmem surface - either explicit or a software driver pSurf->fpVidMem = (ULONG_PTR)pCreateSurface->pSList[i].pbPixels; pSurf->dwLinearSize = pCreateSurface->pSList[i].iPitch; pSurf->lPitch = pCreateSurface->pSList[i].iPitch; pSurf->lSlicePitch = pCreateSurface->pSList[i].iSlicePitch; } else { pSurf->fpVidMem = (ULONG_PTR)pDDSurfaceGlobal[i].fpVidMem; pSurf->dwLinearSize = pDDSurfaceGlobal[i].dwLinearSize; pCreateSurface->pSList[i].iPitch = pSurf->dwLinearSize; pSurf->lPitch = pDDSurfaceGlobal[i].lPitch; if ((pSurf->Type == D3DRTYPE_VOLUME) || (pSurf->Type == D3DRTYPE_VOLUMETEXTURE)) { pSurf->lSlicePitch = pDDSurfaceGlobal[i].dwBlockSizeY; } else { pSurf->lSlicePitch = 0; } } // If it's a software driver, we may need to attach surfaces if ((0==(pSurf->dwFlags & DDSURF_HAL)) && (IS_SOFTWARE_DRIVER(pCreateSurface->hDD)) && (i > 0)) { // Cubes are created strangely... Each face is attached to the root, // and each mipsublevel is attached to its face DDASSERT(pCreateSurface->Type != D3DRTYPE_CUBETEXTURE || pCreateSurface->dwSCnt>=6); SwDDIAttachSurfaces ( ((PDDSURFHANDLE)pCreateSurface->pSList[ SelectAttachmentSurface(pCreateSurface,i) ].hKernelHandle)->pLcl, pSurf->pLcl); } } // If it's a software driver, we need to call CreateSurfaceEx after // all of the attachments are made. if ((IS_SOFTWARE_DRIVER(pCreateSurface->hDD)) && (pSurf->dwCookie != 0)) { SwDDICreateSurfaceEx (pDevice->pDD, ((PDDSURFHANDLE)pCreateSurface->pSList[0].hKernelHandle)->pLcl); } // Now save the surfaces in a 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++) { ((PDDSURFHANDLE)(pCreateSurface->pSList[i].hKernelHandle))->pNext = pDevice->pSurfList; ((PDDSURFHANDLE)(pCreateSurface->pSList[i].hKernelHandle))->pPrevious = NULL; if (pDevice->pSurfList != NULL) { pDevice->pSurfList->pPrevious = (PDDSURFHANDLE)(pCreateSurface->pSList[i].hKernelHandle); } pDevice->pSurfList = (PDDSURFHANDLE)(pCreateSurface->pSList[i].hKernelHandle); } } CleanupCreate: if (1 != dwNumToCreate) { if (pDDSurfaceLocal != NULL) { MemFree(pDDSurfaceLocal); } if (pDDSurfaceGlobal != NULL) { MemFree(pDDSurfaceGlobal); } if (pDDSurfaceMore != NULL) { MemFree(pDDSurfaceMore); } if (phInSurface != NULL) { MemFree(phInSurface); } if (phOutSurface != NULL) { MemFree(phOutSurface); } } if (FAILED(hr)) { // Clean everything up for (i = 0; i < dwNumToCreate; i++) { pSurf = (PDDSURFHANDLE) pCreateSurface->pSList[i].hKernelHandle; if (pSurf != NULL) { FreeSurfaceObject(pSurf); // 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; } } return(MapLegacyResult(hr)); } /******************************Public*Routine******************************\ * * D3dContextCreate * * History: * Mon Jun 03 14:18:29 1996 -by- Drew Bliss [drewb] * Created * \**************************************************************************/ #undef DPF_MODNAME #define DPF_MODNAME "D3dContextCreate" DWORD WINAPI D3dContextCreate(PD3D8_CONTEXTCREATEDATA pCreateContext) { PD3DCONTEXTHANDLE pContext = NULL; BOOL bIsLost = FALSE; DWORD dwRet = DDHAL_DRIVER_HANDLED; // Don't call the driver if the device is lost pCreateContext->ddrval = S_OK; if (!CheckForDeviceLost (pCreateContext->hDD)) { dwRet = OsThunkD3dContextCreate(DDHANDLE(pCreateContext->hDD), GetSurfHandle(pCreateContext->hSurface), GetSurfHandle(pCreateContext->hDDSZ), (D3DNTHAL_CONTEXTCREATEI *)pCreateContext); if (pCreateContext->ddrval == DDERR_SURFACELOST) { bIsLost = TRUE; pCreateContext->ddrval = S_OK; CheckForDeviceLost (pCreateContext->hDD); } } else { bIsLost = TRUE; } // We need to abstract the handle for a couple of reasons: // 1. The context handle can change due to lost devices, and // we'd prefer to abstract this from D3D. // 2. We need to know the device that this handle belongs to // so we can always check for device lost. if (pCreateContext->ddrval == S_OK) { pContext = (PD3DCONTEXTHANDLE) MemAlloc(sizeof(D3DCONTEXTHANDLE)); if (pContext == NULL) { // smac: clean up pCreateContext->dwhContext = (ULONG_PTR) NULL; pCreateContext->ddrval = E_OUTOFMEMORY; } else { pContext->pDevice = pCreateContext->hDD; if (bIsLost) { pContext->dwFlags = D3DCONTEXT_DEFERCREATE; pContext->dwPID = pCreateContext->dwPID; pContext->hDeferHandle = (HANDLE)pCreateContext->dwhContext; pContext->pSurface = pCreateContext->hSurface; pContext->pDDSZ = pCreateContext->hDDSZ; } else { pContext->dwhContext = (HANDLE) pCreateContext->dwhContext; } pCreateContext->dwhContext = (ULONG_PTR) pContext; } } pCreateContext->ddrval = MapLegacyResult(pCreateContext->ddrval); return dwRet; } /******************************Public*Routine******************************\ * * D3dContextDestroy * * History: * Mon Jun 03 14:18:29 1996 -by- Drew Bliss [drewb] * Created * \**************************************************************************/ #undef DPF_MODNAME #define DPF_MODNAME "D3dContextDestroy" DWORD WINAPI D3dContextDestroy(PD3D8_CONTEXTDESTROYDATA pDestroyContext) { PD3DCONTEXTHANDLE pContext = (PD3DCONTEXTHANDLE) pDestroyContext->dwhContext; CheckForDeviceLost (pContext->pDevice); pDestroyContext->ddrval = S_OK; if (pContext->dwhContext) { pDestroyContext->dwhContext = (LONG_PTR) pContext->dwhContext; OsThunkD3dContextDestroy((LPD3DNTHAL_CONTEXTDESTROYDATA) pDestroyContext); } pContext->pDevice->pContext = NULL; MemFree(pContext); pDestroyContext->ddrval = MapLegacyResult(pDestroyContext->ddrval); return DDHAL_DRIVER_HANDLED; } /******************************Public*Routine******************************\ * * D3dContextDestroyAll * * History: * Mon Jun 03 14:18:29 1996 -by- Drew Bliss [drewb] * Created * \**************************************************************************/ #undef DPF_MODNAME #define DPF_MODNAME "D3dContextDestroyAll" DWORD WINAPI D3dContextDestroyAll(PD3D8_CONTEXTDESTROYALLDATA pDestroyAllContext) { OsThunkD3dContextDestroyAll((LPD3DNTHAL_CONTEXTDESTROYALLDATA) pDestroyAllContext); // smac: Need to add code here to free all contexts for each device // the PID has? return DDHAL_DRIVER_HANDLED; } /******************************Public*Routine******************************\ * * DdGetDriverState * * History: * Mon Jun 03 14:18:29 1996 -by- Drew Bliss [drewb] * Created * \**************************************************************************/ #undef DPF_MODNAME #define DPF_MODNAME "DdGetDriverState" DWORD WINAPI DdGetDriverState(PD3D8_GETDRIVERSTATEDATA pGetDriverState) { PD3DCONTEXTHANDLE pContext = (PD3DCONTEXTHANDLE) pGetDriverState->dwhContext; DWORD dwRet = DDHAL_DRIVER_HANDLED; ULONG_PTR pTemp; pGetDriverState->ddRVal = E_FAIL; if (!CheckForDeviceLost (pContext->pDevice)) { pTemp = pGetDriverState->dwhContext; pGetDriverState->dwhContext = (ULONG_PTR) pContext->dwhContext; dwRet = OsThunkDdGetDriverState ((DD_GETDRIVERSTATEDATA*)pGetDriverState); pGetDriverState->dwhContext = pTemp; if (pGetDriverState->ddRVal == DDERR_SURFACELOST) { pGetDriverState->ddRVal = E_FAIL; } } pGetDriverState->ddRVal = MapLegacyResult(pGetDriverState->ddRVal); return dwRet; } /******************************Public*Routine******************************\ * * D3dValidateTextureStageState * * History: * Mon Jun 03 14:18:29 1996 -by- Drew Bliss [drewb] * Created * \**************************************************************************/ #undef DPF_MODNAME #define DPF_MODNAME "D3dValidateTextureStageState" DWORD WINAPI D3dValidateTextureStageState(PD3D8_VALIDATETEXTURESTAGESTATEDATA pValidate) { PD3DCONTEXTHANDLE pContext = (PD3DCONTEXTHANDLE) pValidate->dwhContext; DWORD dwRet = DDHAL_DRIVER_HANDLED; ULONG_PTR pTemp; pValidate->ddrval = D3DERR_DEVICELOST; pValidate->dwNumPasses = 0; if (!CheckForDeviceLost (pContext->pDevice)) { pTemp = pValidate->dwhContext; pValidate->dwhContext = (ULONG_PTR) pContext->dwhContext; dwRet = OsThunkD3dValidateTextureStageState((D3DNTHAL_VALIDATETEXTURESTAGESTATEDATA*)pValidate); pValidate->dwhContext = pTemp; if (pValidate->ddrval == DDERR_SURFACELOST) { pValidate->ddrval = D3DERR_DEVICELOST; } } return dwRet; } /******************************Public*Routine******************************\ * * D3dDrawPrimitives2 * * History: * Mon Jun 17 13:27:05 1996 -by- Anantha Kancherla [anankan] * Created * \**************************************************************************/ #undef DPF_MODNAME #define DPF_MODNAME "D3dDrawPrimitives2" DWORD WINAPI D3dDrawPrimitives2(PD3D8_DRAWPRIMITIVES2DATA pdp2data) { PD3DCONTEXTHANDLE pContext = (PD3DCONTEXTHANDLE) pdp2data->dwhContext; DWORD dwRet = DDHAL_DRIVER_HANDLED; ULONG_PTR pTemp; if (CheckForDeviceLost (pContext->pDevice)) { goto DeviceLost; } pTemp = pdp2data->dwhContext; pdp2data->dwhContext = (ULONG_PTR) pContext->dwhContext; if (pdp2data->dwFlags & D3DHALDP2_USERMEMVERTICES) { dwRet = OsThunkD3dDrawPrimitives2 ( GetSurfHandle(pdp2data->hDDCommands), NULL, // No DDraw surface, pass NULL handle (LPD3DNTHAL_DRAWPRIMITIVES2DATA)pdp2data, &((PDDSURFHANDLE)(pdp2data->hDDCommands))->fpVidMem, &((PDDSURFHANDLE)(pdp2data->hDDCommands))->dwLinearSize, NULL, NULL ); if (dwRet == DDHAL_DRIVER_HANDLED) { if (pdp2data->ddrval == DDERR_SURFACELOST) { pdp2data->dwhContext = pTemp; goto DeviceLost; } else if ((pdp2data->ddrval != S_OK) && (DDERR_WASSTILLDRAWING != pdp2data->ddrval) ) { pContext->pDevice->dwFlags |= DDDEVICE_DP2ERROR; } } pdp2data->fpVidMem_CB = ((PDDSURFHANDLE)(pdp2data->hDDCommands))->fpVidMem; pdp2data->dwLinearSize_CB = ((PDDSURFHANDLE)(pdp2data->hDDCommands))->dwLinearSize; pdp2data->fpVidMem_VB = 0; pdp2data->dwLinearSize_VB = 0; } else { dwRet = OsThunkD3dDrawPrimitives2 ( GetSurfHandle(pdp2data->hDDCommands), GetSurfHandle(pdp2data->hDDVertex), (LPD3DNTHAL_DRAWPRIMITIVES2DATA)pdp2data, &((PDDSURFHANDLE)(pdp2data->hDDCommands))->fpVidMem, &((PDDSURFHANDLE)(pdp2data->hDDCommands))->dwLinearSize, &((PDDSURFHANDLE)(pdp2data->hDDVertex))->fpVidMem, &((PDDSURFHANDLE)(pdp2data->hDDVertex))->dwLinearSize ); if (dwRet == DDHAL_DRIVER_HANDLED) { if (pdp2data->ddrval == DDERR_SURFACELOST) { pdp2data->dwhContext = pTemp; goto DeviceLost; } else if ((pdp2data->ddrval != S_OK) && (DDERR_WASSTILLDRAWING != pdp2data->ddrval) ) { pContext->pDevice->dwFlags |= DDDEVICE_DP2ERROR; } } pdp2data->fpVidMem_CB = ((PDDSURFHANDLE)(pdp2data->hDDCommands))->fpVidMem; pdp2data->dwLinearSize_CB = ((PDDSURFHANDLE)(pdp2data->hDDCommands))->dwLinearSize; pdp2data->fpVidMem_VB = ((PDDSURFHANDLE)(pdp2data->hDDVertex))->fpVidMem; pdp2data->dwLinearSize_VB = ((PDDSURFHANDLE)(pdp2data->hDDVertex))->dwLinearSize; } pdp2data->dwhContext = pTemp; return dwRet; DeviceLost: pdp2data->ddrval = S_OK; pdp2data->dwErrorOffset = 0; // Need to set these values to their original // state so that the FE doesn't get confused. pdp2data->fpVidMem_CB = ((PDDSURFHANDLE)(pdp2data->hDDCommands))->fpVidMem; pdp2data->dwLinearSize_CB = ((PDDSURFHANDLE)(pdp2data->hDDCommands))->dwLinearSize; if (pdp2data->dwFlags & D3DHALDP2_USERMEMVERTICES) { pdp2data->fpVidMem_VB = 0; pdp2data->dwLinearSize_VB = 0; } else { pdp2data->fpVidMem_VB = ((PDDSURFHANDLE)(pdp2data->hDDVertex))->fpVidMem; pdp2data->dwLinearSize_VB = ((PDDSURFHANDLE)(pdp2data->hDDVertex))->dwLinearSize; } // Don't map the legacy result because the runtime needs to handle the // WASSTILLDRAWING case. The runtime will do this mapping for us. return DDHAL_DRIVER_HANDLED; } LPRGNDATA GetClipList(HWND hWnd) { int APIENTRY GetRandomRgn(HDC hdc, HRGN hrgn, int iNum); int rc; HRESULT ddrval = S_OK; DWORD dwSize; DWORD cbRealSize; HDC hdc; HRGN hrgn; LPRGNDATA lpClipList; hdc = GetDC(hWnd); if (hdc == NULL) { DPF_ERR("GetDC failed. Unable to accelerate Present."); return NULL; } // Create the appropriate Region object hrgn = CreateRectRgn(0, 0, 0, 0); if (hrgn == NULL) { DPF_ERR("CreateRectRgn failed. Unable to accelerate Present."); ReleaseDC(hWnd, hdc); return NULL; } // Set the Region to the DC if (-1 == GetRandomRgn(hdc, hrgn, 4)) { DPF_ERR("GetRandomRgn failed. Unable to accelerate Present."); ReleaseDC(hWnd, hdc); DeleteObject(hrgn); return NULL; } // Get the size dwSize = GetRegionData(hrgn, 0, NULL); if (0 == dwSize) { // Release allocations ReleaseDC(hWnd, hdc); DeleteObject(hrgn); return NULL; } do { lpClipList = (LPRGNDATA)MemAlloc(dwSize); if (NULL == lpClipList) { // Release allocations ReleaseDC(hWnd, hdc); DeleteObject(hrgn); return NULL; } // Get the window's region's REGIONDATA cbRealSize = GetRegionData(hrgn, dwSize, lpClipList); if (cbRealSize > dwSize) { MemFree(lpClipList); dwSize = cbRealSize; // make it bigger and try again } else { break; // succeeded } }while(TRUE); ReleaseDC(hWnd, hdc); DeleteObject(hrgn); if (cbRealSize == 0) { DPF_ERR("GetRegionData failed. Unable to accelerate Present."); MemFree(lpClipList); return NULL; } return lpClipList; } /* * ClipRgnToRect */ void ClipRgnToRect(LPRECT prect, LPRGNDATA prd) { RECT rect; int i; int n; LPRECTL prectlD; LPRECTL prectlS; if (prect == NULL || prd == NULL) { return; } // If the bounding rect of the region is exactly equal to // or inside of the Restricting rect then we know // we don't have to do any more work. // // In the common case, the rcBound will be the client // area of a window and so will the restricting rect. if (prect->top <= prd->rdh.rcBound.top && prect->bottom >= prd->rdh.rcBound.bottom && prect->left <= prd->rdh.rcBound.left && prect->right >= prd->rdh.rcBound.right) { return; } // If the bounding rect doesn't equal the prect then // we might have to do some clipping. rect = *prect; prectlD = (LPRECTL) prd->Buffer; prectlS = (LPRECTL) prd->Buffer; n = (int)prd->rdh.nCount; for (i=0; ileft = max(prectlS->left, rect.left); prectlD->right = min(prectlS->right, rect.right); prectlD->top = max(prectlS->top, rect.top); prectlD->bottom= min(prectlS->bottom, rect.bottom); prectlS++; if ((prectlD->bottom - prectlD->top <= 0) || (prectlD->right - prectlD->left <= 0)) { prd->rdh.nCount--; // dont count empty rect. } else { prectlD++; } } return; } /* ClipRgnToRect */ /* * XformRect * * Transform a clipped rect in destination space to the corresponding clipped * rect in src space. So, if we're stretching from src to dest, this yields * the unstretched clipping rect in src space. * * PARAMETERS: * prcSrc - unclipped rect in the source space * prcDest - unclipped rect in the destination space * prcClippedDest - the rect we want to transform * prcClippedSrc - the resulting rect in the source space. return value. * scale_x - 16.16 fixed point src/dest width ratio * scale_y - 16.16 fixed point src/dest height ratio * * DESCRIPTION: * Given an rect in source space and a rect in destination space, and a * clipped rectangle in the destination space (prcClippedDest), return * the rectangle in the source space (prcClippedSrc) that maps to * prcClippedDest. * * Use 16.16 fixed point math for more accuracy. (Shift left, do math, * shift back (w/ round)) * * RETURNS: * S_OK always. prcClippedSrc is the mapped rectangle. * */ HRESULT XformRect(RECT * prcSrc, RECT * prcDest, RECT * prcClippedDest, RECT * prcClippedSrc, DWORD scale_x, DWORD scale_y) { /* * This first calculation is done with fixed point arithmetic (16.16). * The result is converted to (32.0) below. Scale back into source space */ prcClippedSrc->left = (prcClippedDest->left - prcDest->left) * scale_x; prcClippedSrc->right = (prcClippedDest->right - prcDest->left) * scale_x; prcClippedSrc->top = (prcClippedDest->top - prcDest->top) * scale_y; prcClippedSrc->bottom = (prcClippedDest->bottom - prcDest->top) * scale_y; /* * now round (adding 0x8000 rounds) and translate (offset by the * src offset) */ prcClippedSrc->left = (((DWORD)prcClippedSrc->left + 0x8000) >> 16) + prcSrc->left; prcClippedSrc->right = (((DWORD)prcClippedSrc->right + 0x8000) >> 16) + prcSrc->left; prcClippedSrc->top = (((DWORD)prcClippedSrc->top + 0x8000) >> 16) + prcSrc->top; prcClippedSrc->bottom = (((DWORD)prcClippedSrc->bottom + 0x8000) >> 16) + prcSrc->top; /* * Check for zero-sized source rect dimensions and bump if necessary */ if (prcClippedSrc->left == prcClippedSrc->right) { if (prcClippedSrc->right == prcSrc->right) { (prcClippedSrc->left)--; } else { (prcClippedSrc->right)++; } } if (prcClippedSrc->top == prcClippedSrc->bottom) { if (prcClippedSrc->bottom == prcSrc->bottom) { (prcClippedSrc->top)--; } else { (prcClippedSrc->bottom)++; } } return S_OK; } /* XformRect */ /*****************************Private*Routine******************************\ * DdBlt * * History: * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo] * Wrote it. * 31-Mar-2000 -by- Kan Qiu [kanqiu] * Made it handle clipping case \**************************************************************************/ #undef DPF_MODNAME #define DPF_MODNAME "DdBlt" #define SIZE_OF_A_CLIPLIST(lpRgn) \ (sizeof(RGNDATAHEADER)+sizeof(RECTL)*lpRgn->rdh.nCount) DWORD WINAPI DdBlt( PD3D8_BLTDATA pBlt ) { DDHAL_BLTDATA bd; DWORD ret = DDHAL_DRIVER_NOTHANDLED; PDDSURFHANDLE pDstSurf = (PDDSURFHANDLE) pBlt->hDestSurface; PDDSURFHANDLE pSrcSurf = (PDDSURFHANDLE) pBlt->hSrcSurface; PDDDEVICEHANDLE pDevice = (PDDDEVICEHANDLE) pBlt->hDD; DWORD bltcaps; 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 && ((pDstSurf->Pool == D3DPOOL_LOCALVIDMEM) || (pDstSurf->Pool == D3DPOOL_NONLOCALVIDMEM)) ) { pBlt->ddRVal = S_OK; } else { pBlt->ddRVal = D3DERR_DEVICELOST; } return DDHAL_DRIVER_HANDLED; } ZeroMemory(&bd, sizeof bd); bd.ddRVal = E_FAIL; // always assume error // Just a colorfill? #ifdef DEBUG if ((pSrcSurf == NULL) && pDstSurf) { do { bd.dwFlags = pBlt->dwFlags & DDBLT_VALID; bd.IsClipped = FALSE; // NT Kernel cannot handle it bd.bltFX = pBlt->bltFX; bd.rDest = pBlt->rDest; ret = OsThunkDdBlt(GetSurfHandle(pBlt->hDestSurface), 0, (PDD_BLTDATA) &bd); if (DDHAL_DRIVER_NOTHANDLED == ret) { DPF_ERR("Driver failed color-fill blt. SWAPEFFECT_DISCARD not being enforced."); } } while (bd.ddRVal == DDERR_WASSTILLDRAWING); return S_OK; } #endif // Are we going to send this blt to the driver? if (!pDstSurf) { // NULL destination ? we are running SW driver w/o ddraw support // use GDI for blting goto gdiblt; } else if (IS_SOFTWARE_DRIVER_SURFACE(pSrcSurf)) { if (!(pDevice->DDCaps & DDCAPS_CANBLTSYSMEM)) goto gdiblt; bltcaps = pDevice->SVBCaps; } else { bltcaps = pDevice->DDCaps; } if (!(bltcaps & DDCAPS_BLT)) goto gdiblt; //it is assumed that the format for a presented back buffer is OK and has //been validated by higher layers of the runtime. (e.g. if the back //buffer has alpha, or in the future is very different from front buffer format) if ((pDstSurf->Format == pSrcSurf->Format) || (pBlt->dwFlags & DDBLT_WINDOWCLIP) ) //which means this is a presentation blt { //Yes, we're going to the driver... bd.rDest = pBlt->rDest; bd.rSrc = pBlt->rSrc; bd.dwFlags = pBlt->dwFlags & DDBLT_VALID; bd.dwROPFlags = pBlt->dwROPFlags; bd.IsClipped = FALSE; // NT Kernel cannot handle it bd.bltFX = pBlt->bltFX; // This is for Window Redirection support // (available on post-Windows 2000) // On Windows 2000, bd.Blt is ignored by win32k.sys if (pBlt->dwFlags & DDBLT_WINDOWCLIP) { bd.Blt = (VOID*)(pBlt->hWnd); } // Mask DX8 flags from the OS if (pBlt->dwFlags & DDBLT_DX8ORHIGHER) { bd.dwFlags &= ~(DDBLT_WINDOWCLIP | DDBLT_COPYVSYNC | DDBLT_DX8ORHIGHER); } DPF(10,"pBlt->rDest %08lx %08lx %08lx %08lx", pBlt->rDest.top, pBlt->rDest.bottom, pBlt->rDest.left, pBlt->rDest.right); if ((pBlt->hWnd) && (DDBLT_WINDOWCLIP & pBlt->dwFlags)) { RECTL rOrigSrc=pBlt->rSrc; // unclipped src rect LONG SrcWidth = rOrigSrc.right - rOrigSrc.left; LONG SrcHeight = rOrigSrc.bottom - rOrigSrc.top; RECT rOrigDest; do { LPRGNDATA prd; LPRECT prect; DWORD cnt; if (GetClientRect(pBlt->hWnd, &rOrigDest)) { POINT pOrigDest; if (rOrigDest.right > pBlt->rDest.right) rOrigDest.right = pBlt->rDest.right; if (rOrigDest.bottom > pBlt->rDest.bottom) rOrigDest.bottom = pBlt->rDest.bottom; if (0 < pBlt->rDest.left) rOrigDest.left = pBlt->rDest.left; if (0 < pBlt->rDest.top) rOrigDest.top = pBlt->rDest.top; if ((rOrigDest.right <= rOrigDest.left) || (rOrigDest.bottom <= rOrigDest.top) ) { pBlt->ddRVal = S_OK; return DDHAL_DRIVER_HANDLED; } pOrigDest.x = - pDevice->rcMonitor.left; pOrigDest.y = - pDevice->rcMonitor.top; if (!ClientToScreen(pBlt->hWnd, &pOrigDest)) DPF_ERR("ClientToScreen Failed on pOrigDest?"); if (!OffsetRect(&rOrigDest, pOrigDest.x, pOrigDest.y )) DPF_ERR("OffsetRect Failed on rOrigDest?"); if (rOrigDest.bottom <= 0 || rOrigDest.right <= 0 || (rOrigDest.top + pDevice->rcMonitor.top >= pDevice->rcMonitor.bottom) || (rOrigDest.left + pDevice->rcMonitor.left >= pDevice->rcMonitor.right)) { // client is completely outside device space // means cross device blt is needed goto gdiblt; } } else { DPF_ERR("GetClientRect Failed ?"); goto gdiblt; } if ( ( NULL == pDevice->pClipList ) || ( NULL == pDevice->pOrigClipList ) || ( pDevice->hLastWnd != pBlt->hWnd ) || (DDERR_VISRGNCHANGED == bd.ddRVal)) { DWORD dwClipListSize; if ( NULL != pDevice->pClipList ) { MemFree(pDevice->pClipList); pDevice->pClipList = NULL; } if ( NULL != pDevice->pOrigClipList ) { MemFree(pDevice->pOrigClipList); pDevice->pOrigClipList = NULL; } prd = GetClipList(pBlt->hWnd); if (NULL == prd) goto gdiblt; prect=(LPRECT) &prd->Buffer[0]; for (cnt=0; cntrdh.nCount; cnt++) { if ((prect[cnt].top < pDevice->rcMonitor.top) || (prect[cnt].left < pDevice->rcMonitor.left) || (prect[cnt].bottom > pDevice->rcMonitor.bottom) || (prect[cnt].right > pDevice->rcMonitor.right) ) { // do GDI blt if any rect is outside MemFree (prd); goto gdiblt; } if (!OffsetRect( &prect[cnt], - pDevice->rcMonitor.left, - pDevice->rcMonitor.top )) DPF_ERR("OffsetRect Failed on prect[cnt]?"); } dwClipListSize = SIZE_OF_A_CLIPLIST(prd); pDevice->pOrigClipList = (LPRGNDATA)MemAlloc(dwClipListSize); if (NULL != pDevice->pOrigClipList) { memcpy(pDevice->pOrigClipList, prd, dwClipListSize); pDevice->hLastWnd = pBlt->hWnd; } } else { prd = pDevice->pClipList; memcpy(prd, pDevice->pOrigClipList, SIZE_OF_A_CLIPLIST(pDevice->pOrigClipList)); } DDASSERT( (0 == pDevice->pClipList) || ( prd == pDevice->pClipList) ); DDASSERT( NULL != prd ); // Clip the region to the rect before we go further ClipRgnToRect(&rOrigDest, prd ); // Process each visible sub-rect separately if (prd->rdh.nCount > 0) { int x_offset; int y_offset; DWORD scale_x; DWORD scale_y; BOOL stretch_blt; pDevice->pClipList = prd; // precalculate a couple of variables if ((rOrigDest.bottom - rOrigDest.top == SrcHeight) && (rOrigDest.right - rOrigDest.left == SrcWidth)) { x_offset = rOrigSrc.left - rOrigDest.left; y_offset = rOrigSrc.top - rOrigDest.top; stretch_blt = FALSE; } else { if (!(bltcaps & DDCAPS_BLTSTRETCH)) goto gdiblt; // scale_x and scale_y are fixed point variables scaled // 16.16 (16 integer bits and 16 fractional bits) scale_x = (SrcWidth << 16) / (rOrigDest.right - rOrigDest.left); scale_y = (SrcHeight << 16) / (rOrigDest.bottom - rOrigDest.top); stretch_blt = TRUE; } if (DDBLT_COPYVSYNC & pBlt->dwFlags) { DD_GETSCANLINEDATA ScanData; DWORD msStartTime = GetTickCount(); DWORD msCurrentTime; DWORD threshold=pBlt->threshold; // Compute how many milliseconds there // are per refresh. We round down. msCurrentTime = msStartTime; // If the previous blt was just a few ms ago // then we can make up the difference by yielding if ((msCurrentTime - pBlt->msLastPresent) < threshold ) { Sleep(threshold + pBlt->msLastPresent - msCurrentTime); msCurrentTime = pBlt->msLastPresent + threshold; } threshold = ((PDDSURFHANDLE)pBlt->hDestSurface)->dwHeight/2; while (DDHAL_DRIVER_HANDLED == OsThunkDdGetScanLine(DDHANDLE(pBlt->hDD),&ScanData)) { if (DD_OK != ScanData.ddRVal) break; if ((LONG)ScanData.dwScanLine >= rOrigDest.bottom) break; if ((LONG)(ScanData.dwScanLine + threshold/3) < rOrigDest.top) break; // just yield 1 ms instead of doing lengthy calculation which // does not get me better result if ((LONG)(ScanData.dwScanLine + threshold) < rOrigDest.bottom) { Sleep(1); } // If we've been spinning here for 30ms // then blt anyway; probably something // running in the background taking // up CPU cycles msCurrentTime = GetTickCount(); if ((msCurrentTime - msStartTime) > 30) { break; } } // Remember the time of last blt pBlt->msLastPresent = msCurrentTime; } //traverse the visible rect list and send each piece to //the driver to blit prect=(LPRECT) &prd->Buffer[0]; for (cnt=0;cntrdh.nCount;cnt++) { // find out where on the src rect we need to get // the data from. bd.rDest.left = prect[cnt].left; bd.rDest.right = prect[cnt].right; bd.rDest.top = prect[cnt].top; bd.rDest.bottom = prect[cnt].bottom; if (!stretch_blt) { // no stretch // one-to-one mapping from source to destination bd.rSrc.left = bd.rDest.left + x_offset; bd.rSrc.right = bd.rDest.right + x_offset; bd.rSrc.top = bd.rDest.top + y_offset; bd.rSrc.bottom = bd.rDest.bottom + y_offset; } else { // stretching // linear mapping from source to destination // calculate the source rect which transforms to the // dest rect XformRect((RECT *)&(rOrigSrc), &rOrigDest, (RECT *)&(bd.rDest), (RECT *)&(bd.rSrc), scale_x, scale_y); } // If mirror Blt, we must fix up source rect here! if (bd.dwFlags & DDBLT_DDFX) { int temp; if (bd.bltFX.dwDDFX & DDBLTFX_MIRRORLEFTRIGHT) { temp = bd.rSrc.left; bd.rSrc.left = rOrigSrc.left + rOrigSrc.right - bd.rSrc.right; bd.rSrc.right = rOrigSrc.left + rOrigSrc.right - temp; } if (bd.bltFX.dwDDFX & DDBLTFX_MIRRORUPDOWN) { temp = bd.rSrc.top; bd.rSrc.top = rOrigSrc.top + rOrigSrc.bottom - bd.rSrc.bottom; bd.rSrc.bottom = rOrigSrc.top + rOrigSrc.bottom - temp; } } do { bd.ddRVal = E_FAIL; // always assume error if (bd.dwFlags & DDBLT_PRESENTATION) { if (cnt == prd->rdh.nCount-1) { bd.dwFlags |= DDBLT_LAST_PRESENTATION; } } ret = OsThunkDdBlt(GetSurfHandle(pBlt->hDestSurface), GetSurfHandle(pBlt->hSrcSurface), (PDD_BLTDATA) &bd); if (DDHAL_DRIVER_NOTHANDLED == ret) { bd.ddRVal = E_FAIL; // make it out of loop break; } if (bd.ddRVal == DDERR_SURFACELOST) { bd.ddRVal = S_OK; break; } /* * NOTE: If clipping has introduced more than * one rectangle we behave as if DDBLT_WAIT * was specified on all rectangles after the * first. This is necessary as the first * rectangle will probably cause the accelerator * to be busy. Hence, the attempt to blit the * second rectangle will fail with * DDERR_WASSTILLDRAWING. If we pass this to * the application (rather than busy waiting) * the application is likely to retry the blit * (which will fail on the second rectangle again) * and we have an application sitting in an * infinite loop). */ } while( (DDERR_WASSTILLDRAWING == bd.ddRVal) && ( (DDBLT_WAIT & pBlt->dwFlags) || (1 < prd->rdh.nCount) ) ); if (FAILED(bd.ddRVal)) break; } } else { MemFree (prd); pDevice->pClipList = NULL; bd.ddRVal = S_OK; ret = DDHAL_DRIVER_HANDLED; break; // all clipped, no need to blt! } if (DDERR_VISRGNCHANGED == bd.ddRVal) { OsThunkDdResetVisrgn(GetSurfHandle(pBlt->hDestSurface),(HWND)0); pDevice->hLastWnd = NULL; // zero cached info for DdBlt } } while (DDERR_VISRGNCHANGED == bd.ddRVal); } else { DDASSERT( 0 == (bd.dwFlags & DDBLT_PRESENTATION)); if ((bd.rDest.right - bd.rDest.left != bd.rSrc.right - bd.rSrc.left || bd.rDest.bottom - bd.rDest.top != bd.rSrc.bottom - bd.rSrc.top) && !(bltcaps & DDCAPS_BLTSTRETCH) ) goto gdiblt; do { bd.ddRVal = E_FAIL; // always assume error ret = OsThunkDdBlt(GetSurfHandle(pBlt->hDestSurface), GetSurfHandle(pBlt->hSrcSurface), (PDD_BLTDATA) &bd); if (DDHAL_DRIVER_NOTHANDLED == ret) { bd.ddRVal = E_FAIL; // make it out of loop break; } if (bd.ddRVal == DDERR_SURFACELOST) { bd.ddRVal = S_OK; } if (DDERR_VISRGNCHANGED == bd.ddRVal) { OsThunkDdResetVisrgn(GetSurfHandle(pBlt->hDestSurface),(HWND)0); pDevice->hLastWnd = NULL; // zero cached info for DdBlt } } while ( (DDERR_VISRGNCHANGED == bd.ddRVal) || ( (DDERR_WASSTILLDRAWING == bd.ddRVal) && (DDBLT_WAIT & pBlt->dwFlags) ) ); } } gdiblt: if (FAILED(bd.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; BOOL bGetDCfromWnd = (pBlt->hWnd) && ((DDBLT_WINDOWCLIP & pBlt->dwFlags) || !pBlt->hDestSurface); if (bGetDCfromWnd) 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)) { bd.ddRVal = S_OK; ret = DDHAL_DRIVER_HANDLED; } } 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)) { bd.ddRVal = S_OK; ret = DDHAL_DRIVER_HANDLED; } // restore to previous mode if (saved) SetStretchBltMode(hDCTarget,saved); } D3D8ReleaseDC(pBlt->hSrcSurface, hDCSource); } if (bGetDCfromWnd) ReleaseDC(pBlt->hWnd, hDCTarget); else D3D8ReleaseDC(pBlt->hDestSurface, hDCTarget); } } pBlt->ddRVal = MapLegacyResult(bd.ddRVal); // 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->dwFlags & DDDEVICE_DP2ERROR) && (pBlt->dwFlags & DDBLT_WINDOWCLIP)) { pDevice->dwFlags &= ~DDDEVICE_DP2ERROR; // 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; } return ret; } /*****************************Private*Routine******************************\ * DdFlip * * History: * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo] * Wrote it. \**************************************************************************/ #undef DPF_MODNAME #define DPF_MODNAME "DdFlip" DWORD APIENTRY DdFlip( PD3D8_FLIPDATA pFlip ) { HANDLE hSurfTargLeft=NULL; HANDLE hSurfCurrLeft=NULL; DDHAL_FLIPDATA FlipData; DWORD dwRet; if (CheckForDeviceLost (pFlip->hDD)) { pFlip->ddRVal = S_OK; return DDHAL_DRIVER_HANDLED; } FlipData.dwFlags = (pFlip->dwFlags & ~DDFLIP_WAIT); FlipData.ddRVal = DDERR_GENERIC; if (pFlip->dwFlags & DDFLIP_STEREO) { hSurfTargLeft = GetSurfHandle(pFlip->hSurfTargLeft); hSurfCurrLeft = GetSurfHandle(pFlip->hSurfCurrLeft); } do { dwRet = OsThunkDdFlip(GetSurfHandle(pFlip->hSurfCurr), GetSurfHandle(pFlip->hSurfTarg), hSurfCurrLeft, hSurfTargLeft, (PDD_FLIPDATA) &FlipData); if (FlipData.ddRVal == DDERR_SURFACELOST) { FlipData.ddRVal = S_OK; } }while (DDERR_WASSTILLDRAWING == FlipData.ddRVal && (DDFLIP_WAIT & pFlip->dwFlags)); pFlip->ddRVal = MapLegacyResult(FlipData.ddRVal); // We only want to report DP2 errors during the present call because // checking for it everywhere is too hard. if ((pFlip->ddRVal == DD_OK) && (((DDDEVICEHANDLE*)pFlip->hDD)->dwFlags & DDDEVICE_DP2ERROR)) { ((DDDEVICEHANDLE*)pFlip->hDD)->dwFlags &= ~DDDEVICE_DP2ERROR; // 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; } return dwRet; } /*****************************Private*Routine******************************\ * DdLock * * History: * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo] * Wrote it. \**************************************************************************/ #undef DPF_MODNAME #define DPF_MODNAME "DdLock" HRESULT APIENTRY DdLock( PD3D8_LOCKDATA pLock ) { DD_LOCKDATA LockData; PDDSURFHANDLE pSurf; BOOL bAdjustSlice = FALSE; pSurf = (PDDSURFHANDLE) pLock->hSurface; // If the device is lost, we need to fake up a buffer for // the app to write to. We still allow software drivers // handle the Lock call, however. Further, we also allow // driver managed surfaces to go through. if (CheckForDeviceLost (pLock->hDD) && !IS_SOFTWARE_DRIVER_SURFACE(pSurf) && pSurf->Pool != D3DPOOL_MANAGED) { goto DeviceLost; } // We do make an exception for fake deferred creates // of driver managed surfaces. The driver doesn't know // about these deferred surfaces, so we don't call it. // ASSUMPTIONS: even if DDSURF_SYSMEMALLOCATED can be // set below, we expect it to be never set below for // **driver managed surfaces**. For these surfaces, we // assume that it will be set only in // CreateVidMemSurface. This assumption is true as of // 3/2001. if ((pSurf->dwFlags & DDSURF_SYSMEMALLOCATED) != 0) { DDASSERT(pSurf->fpVidMem != (ULONG_PTR)NULL); goto DeviceLost; } // Mask off new flags LockData.dwFlags = pLock->dwFlags; LockData.dwFlags &= (D3DLOCK_READONLY | D3DLOCK_DISCARD | D3DLOCK_NOOVERWRITE | D3DLOCK_NOSYSLOCK); // Always set lock_wait LockData.dwFlags |= DDLOCK_WAIT; // Also set equivalent DDLOCK flag for NO_DIRTY_UPDATE // if the driver understands it if ((pLock->dwFlags & D3DLOCK_NO_DIRTY_UPDATE) != 0) { LockData.dwFlags |= DDLOCK_NODIRTYUPDATE; } if(pLock->bHasRange) { LockData.bHasRect = TRUE; LockData.rArea.left = 0; LockData.rArea.right = 0; LockData.rArea.top = pLock->range.Offset; LockData.rArea.bottom = pLock->range.Offset + pLock->range.Size; } else { LockData.bHasRect = pLock->bHasRect; LockData.rArea = pLock->rArea; } if (pLock->bHasBox) { LockData.bHasRect = TRUE; LockData.rArea.left = pLock->box.Left; LockData.rArea.right = pLock->box.Right; LockData.rArea.top = pLock->box.Top; LockData.rArea.bottom = pLock->box.Bottom; // We cannot change the kernel for an OS before whistler, so we will // not pass the front/back to the driver. For ref and for newer OSes, // we will stick the front/back into the high word of left/right if (IS_SOFTWARE_DRIVER_SURFACE(pSurf) || ((((PDDDEVICEHANDLE)pLock->hDD)->bIsWhistler) && (((PDDDEVICEHANDLE)pLock->hDD)->dwFlags & DDDEVICE_SUPPORTSUBVOLUMELOCK))) { LockData.dwFlags |= DDLOCK_HASVOLUMETEXTUREBOXRECT; LockData.rArea.left |= (pLock->box.Front << 16); LockData.rArea.right |= (pLock->box.Back << 16); } else { bAdjustSlice = TRUE; } } LockData.ddRVal = DDERR_WASSTILLDRAWING; if (IS_SOFTWARE_DRIVER_SURFACE(pSurf)) { // This is a software driver, so we need to treat // it specially SwDDILock (pLock->hDD, pSurf, &LockData); } else { while ((LockData.ddRVal == DDERR_VISRGNCHANGED) || (LockData.ddRVal == DDERR_WASSTILLDRAWING)) { if ((pSurf->Type == D3DRTYPE_VERTEXBUFFER) || (pSurf->Type == D3DRTYPE_COMMANDBUFFER)|| (pSurf->Type == D3DRTYPE_INDEXBUFFER)) { OsThunkDdLockD3D(pSurf->hSurface, &LockData); } else { OsThunkDdLock(pSurf->hSurface, &LockData, NULL); } if (LockData.ddRVal == DDERR_VISRGNCHANGED) { if (pLock->dwFlags & DDLOCK_FAILONVISRGNCHANGED) { break; } else { PDDDEVICEHANDLE pDevice = (PDDDEVICEHANDLE) pLock->hDD; OsThunkDdResetVisrgn(pSurf->hSurface, (HWND)0); pDevice->hLastWnd = NULL; // zero cached info for DdBlt } } // In the past we would require DDLOCK_WAIT to // decide if we would spin or exit now we always wait } if (LockData.ddRVal == DDERR_SURFACELOST) { CheckForDeviceLost(pLock->hDD); goto DeviceLost; } } if (LockData.ddRVal == S_OK) { pLock->lpSurfData = LockData.lpSurfData; pLock->lPitch = pSurf->lPitch; if ((pSurf->Type == D3DRTYPE_VOLUME) || (pSurf->Type == D3DRTYPE_VOLUMETEXTURE)) { pLock->lSlicePitch = pSurf->lSlicePitch; if (bAdjustSlice) { ((BYTE*)pLock->lpSurfData) += (pLock->lSlicePitch * pLock->box.Front); } } pSurf->LockRefCnt++; } return MapLegacyResult(LockData.ddRVal); DeviceLost: // At the time the device is lost, fpVidMem is set to NULL // for all vidmem surfaces. Therefore, if it is non-NULL // we are safe to use what we already have; otherwise, we // have to allocate our own. if (pSurf->fpVidMem == (ULONG_PTR) NULL) { if ((pSurf->Type == D3DRTYPE_VOLUME) || (pSurf->Type == D3DRTYPE_VOLUMETEXTURE)) { // For volume textures, dwHeight really contains the depth pSurf->fpVidMem = (ULONG_PTR) MemAlloc(pSurf->lSlicePitch * pSurf->dwHeight); } else { pSurf->fpVidMem = (ULONG_PTR) MemAlloc(pSurf->lPitch * pSurf->dwHeight); } if (pSurf->fpVidMem == (ULONG_PTR) NULL) { pLock->lpSurfData = (void*)pSurf->fpVidMem; return E_FAIL; } pSurf->dwFlags |= DDSURF_SYSMEMALLOCATED; } pLock->lpSurfData = (void*)pSurf->fpVidMem; pLock->lPitch = pSurf->lPitch; if ((pSurf->Type == D3DRTYPE_VOLUME) || (pSurf->Type == D3DRTYPE_VOLUMETEXTURE)) { pLock->lSlicePitch = pSurf->lSlicePitch; } pSurf->LockRefCnt++; return S_OK; } /*****************************Private*Routine******************************\ * DdUnlock * * History: * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo] * Wrote it. \**************************************************************************/ #undef DPF_MODNAME #define DPF_MODNAME "DdUnlock" HRESULT APIENTRY DdUnlock( PD3D8_UNLOCKDATA pUnlock ) { DD_UNLOCKDATA UnlockData; PDDSURFHANDLE pSurf; pSurf = (PDDSURFHANDLE) pUnlock->hSurface; if (pSurf->LockRefCnt > 0) { pSurf->LockRefCnt--; } if (CheckForDeviceLost (pUnlock->hDD) && !IS_SOFTWARE_DRIVER_SURFACE(pSurf) && pSurf->Pool != D3DPOOL_MANAGED) { return S_OK; } if ((pSurf->dwFlags & DDSURF_SYSMEMALLOCATED) != 0) { DDASSERT(pSurf->fpVidMem != (ULONG_PTR)NULL); return S_OK; } if (IS_SOFTWARE_DRIVER_SURFACE(pSurf)) { // This is a software driver, so we need to treat // it specially SwDDIUnlock (pUnlock->hDD, pSurf, &UnlockData); } else { if ((GetSurfType(pUnlock->hSurface) == D3DRTYPE_VERTEXBUFFER) || (GetSurfType(pUnlock->hSurface) == D3DRTYPE_COMMANDBUFFER) || (GetSurfType(pUnlock->hSurface) == D3DRTYPE_INDEXBUFFER)) { OsThunkDdUnlockD3D(GetSurfHandle(pUnlock->hSurface), &UnlockData); } else { OsThunkDdUnlock(GetSurfHandle(pUnlock->hSurface), &UnlockData); } if (UnlockData.ddRVal == DDERR_SURFACELOST) { UnlockData.ddRVal = S_OK; } } return MapLegacyResult(UnlockData.ddRVal); } /*****************************Private*Routine******************************\ * DdGetBltStatus * * History: * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo] * Wrote it. \**************************************************************************/ #undef DPF_MODNAME #define DPF_MODNAME "DdGetBltStatus" DWORD APIENTRY DdGetBltStatus( PD3D8_GETBLTSTATUSDATA pGetBltStatus ) { DDHAL_GETBLTSTATUSDATA StatusData; DWORD dwRet; if (CheckForDeviceLost (pGetBltStatus->hDD)) { pGetBltStatus->ddRVal = S_OK; return DDHAL_DRIVER_HANDLED; } StatusData.dwFlags = pGetBltStatus->dwFlags; dwRet = OsThunkDdGetBltStatus(GetSurfHandle(pGetBltStatus->hSurface), (PDD_GETBLTSTATUSDATA) &StatusData); if (StatusData.ddRVal == DDERR_SURFACELOST) { StatusData.ddRVal = S_OK; } pGetBltStatus->ddRVal = MapLegacyResult(StatusData.ddRVal); return dwRet; } /*****************************Private*Routine******************************\ * DdGetFlipStatus * * History: * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo] * Wrote it. \**************************************************************************/ #undef DPF_MODNAME #define DPF_MODNAME "DdGetFlipStatus" DWORD APIENTRY DdGetFlipStatus( PD3D8_GETFLIPSTATUSDATA pGetFlipStatus ) { DDHAL_GETFLIPSTATUSDATA StatusData; DWORD dwRet; if (CheckForDeviceLost (pGetFlipStatus->hDD)) { pGetFlipStatus->ddRVal = S_OK; return DDHAL_DRIVER_HANDLED; } StatusData.dwFlags = pGetFlipStatus->dwFlags; dwRet = OsThunkDdGetFlipStatus(GetSurfHandle(pGetFlipStatus->hSurface), (PDD_GETFLIPSTATUSDATA) &StatusData); if (StatusData.ddRVal == DDERR_SURFACELOST) { StatusData.ddRVal = S_OK; } pGetFlipStatus->ddRVal = MapLegacyResult(StatusData.ddRVal); return dwRet; } /*****************************Private*Routine******************************\ * DdWaitForVerticalBlank * * History: * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo] * Wrote it. \**************************************************************************/ #undef DPF_MODNAME #define DPF_MODNAME "DdWaitForVerticalBlank" DWORD APIENTRY DdWaitForVerticalBlank( PD3D8_WAITFORVERTICALBLANKDATA pWaitForVerticalBlank ) { DDHAL_WAITFORVERTICALBLANKDATA WaitData; DWORD dwRet; if (CheckForDeviceLost (pWaitForVerticalBlank->hDD)) { goto DeviceLost; } WaitData.dwFlags = pWaitForVerticalBlank->dwFlags; WaitData.hEvent = 0; dwRet = OsThunkDdWaitForVerticalBlank(DDHANDLE(pWaitForVerticalBlank->hDD), (PDD_WAITFORVERTICALBLANKDATA) &WaitData); if (WaitData.ddRVal == DDERR_SURFACELOST) { goto DeviceLost; } pWaitForVerticalBlank->bIsInVB = WaitData.bIsInVB; pWaitForVerticalBlank->ddRVal = WaitData.ddRVal; if (WaitData.ddRVal == DDERR_VERTICALBLANKINPROGRESS) { pWaitForVerticalBlank->bIsInVB = TRUE; } else { pWaitForVerticalBlank->bIsInVB = FALSE; } pWaitForVerticalBlank->ddRVal = DD_OK; return dwRet; DeviceLost: { 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; } } return DDHAL_DRIVER_HANDLED; } /*****************************Private*Routine******************************\ * DdDestroySurface * * History: * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo] * Wrote it. \**************************************************************************/ #undef DPF_MODNAME #define DPF_MODNAME "DdDestroySurface" DWORD APIENTRY DdDestroySurface( PD3D8_DESTROYSURFACEDATA pDestroySurface ) { DWORD i; PDDSURFHANDLE pSurf = (PDDSURFHANDLE) pDestroySurface->hSurface; PDDDEVICEHANDLE pDevice = (PDDDEVICEHANDLE) pDestroySurface->hDD; PDEFERREDCREATE pDefCreate = pDevice->pDeferList; FreeSurfaceObject(pSurf); // 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; } // If we allcoated the memory for this surface (due to a lost state), // then we should free it now. if (pSurf->dwFlags & DDSURF_SYSMEMALLOCATED) { MemFree((void*) pSurf->fpVidMem); } // If this surface pointer is cached in the context structure, we need // to remedy that. if (pSurf->pDevice->pContext != NULL) { if (pSurf->pDevice->pContext->pSurface == pSurf) { pSurf->pDevice->pContext->pSurface = NULL; } if (pSurf->pDevice->pContext->pDDSZ == pSurf) { pSurf->pDevice->pContext->pDDSZ = NULL; } } 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 == (PDDSURFHANDLE) pDefCreate->CreateData.pSList[i].hKernelHandle) { pDefCreate->CreateData.pSList[i].hKernelHandle = 0; break; } } pDefCreate = pDefCreate->pNext; } return (DDHAL_DRIVER_HANDLED); } #undef DPF_MODNAME #define DPF_MODNAME "D3D8GetMode" DWORD APIENTRY D3D8GetMode( HANDLE Handle, char* pDeviceName, D3DDISPLAYMODE* pMode, D3DFORMAT Unknown16) { DEVMODE dm; HDC hdc; memset (&dm, 0, sizeof(dm)); dm.dmSize = sizeof(dm); 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 = D3DFMT_R5G6B5; hdc = DD_CreateDC(pDeviceName); if (hdc) { HBITMAP hbm; BITMAPINFO *pbmi; DWORD *pdwColors; if (pbmi = (BITMAPINFO*) MemAlloc(3 * sizeof (RGBQUAD) + sizeof (BITMAPINFO))) { if (hbm = CreateCompatibleBitmap(hdc, 1, 1)) { pbmi->bmiHeader.biSize = sizeof (BITMAPINFOHEADER); if (GetDIBits(hdc, hbm, 0, 0, NULL, pbmi, DIB_RGB_COLORS)) { if (pbmi->bmiHeader.biCompression == BI_BITFIELDS) { GetDIBits(hdc, hbm, 0, pbmi->bmiHeader.biHeight, NULL, pbmi, DIB_RGB_COLORS); pdwColors = (DWORD *) &pbmi->bmiColors[0]; if (pdwColors[1] == 0x3e0) { pMode->Format = D3DFMT_X1R5G5B5; } } } DeleteObject(hbm); } MemFree(pbmi); } DD_DoneDC(hdc); } break; default: pMode->Format = D3DFMT_UNKNOWN; break; } return S_OK; } // I don't know in which cases we would ever hit this return D3DERR_DRIVERINTERNALERROR; } #undef DPF_MODNAME #define DPF_MODNAME "D3D8SetMode" DWORD APIENTRY D3D8SetMode( HANDLE Handle, char* pDeviceName, UINT Width, UINT Height, UINT BPP, UINT RefreshRate, BOOL bRestore) { HANDLE h = GetModuleHandle("USER32"); LONG (WINAPI *pfnChangeDisplaySettingsExA)(LPCSTR,LPDEVMODEA,HWND,DWORD,LPVOID); DEVMODE dm, * pdm; PDDDEVICEHANDLE pDevice = (PDDDEVICEHANDLE) Handle; // Init the devmode properly: dm.dmSize = sizeof(DEVMODE); EnumDisplaySettings (pDeviceName,0,&dm); dm.dmBitsPerPel = BPP; dm.dmPelsWidth = Width; dm.dmPelsHeight = Height; dm.dmDisplayFrequency = RefreshRate; dm.dmDisplayFlags = 0; dm.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY; // Now tell the OS to do the mode change (FARPROC)pfnChangeDisplaySettingsExA = GetProcAddress(h,"ChangeDisplaySettingsExA"); if (pfnChangeDisplaySettingsExA) { InformDriverToDeferFrees(pDevice); if (bRestore) { if ((*pfnChangeDisplaySettingsExA)(pDeviceName, NULL, NULL, CDS_FULLSCREEN, 0) == DISP_CHANGE_SUCCESSFUL) { return S_OK; } } else { if ((*pfnChangeDisplaySettingsExA)(pDeviceName, &dm, NULL, CDS_FULLSCREEN, 0) == DISP_CHANGE_SUCCESSFUL) { return S_OK; } } if (NumReadyDevices == NumDevices) { InformDriverFreeAGP(pDevice); } } return D3DERR_DRIVERINTERNALERROR; } /*****************************Private*Routine******************************\ * DdSetMode * * History: * 29-Nov-1999 -by- Scott MacDonald [smac] * Wrote it. \**************************************************************************/ #undef DPF_MODNAME #define DPF_MODNAME "DdSetMode" DWORD APIENTRY DdSetMode( PD3D8_SETMODEDATA pSetMode ) { UINT BPP; PDDDEVICEHANDLE pDeviceHandle = (PDDDEVICEHANDLE) pSetMode->hDD; // smac: How should lost devices behave? CheckForDeviceLost(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(pDeviceHandle, pDeviceHandle->szDeviceName, pSetMode->dwWidth, pSetMode->dwHeight, BPP, pSetMode->dwRefreshRate, pSetMode->bRestore); return DDHAL_DRIVER_HANDLED; } /*****************************Private*Routine******************************\ * DdGetScanLine * * History: * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo] * Wrote it. \**************************************************************************/ #undef DPF_MODNAME #define DPF_MODNAME "DdGetScanLine" DWORD APIENTRY DdGetScanLine( PD3D8_GETSCANLINEDATA pGetScanLine ) { DDHAL_GETSCANLINEDATA ScanData; DWORD dwRet; if (CheckForDeviceLost(pGetScanLine->hDD)) { goto DeviceLost; } dwRet = OsThunkDdGetScanLine(DDHANDLE(pGetScanLine->hDD), (PDD_GETSCANLINEDATA) &ScanData); if (ScanData.ddRVal == DDERR_SURFACELOST) { goto DeviceLost; } pGetScanLine->dwScanLine = ScanData.dwScanLine; if (ScanData.ddRVal == DDERR_VERTICALBLANKINPROGRESS) { pGetScanLine->bInVerticalBlank = TRUE; ScanData.ddRVal = S_OK; } else { pGetScanLine->bInVerticalBlank = FALSE; } pGetScanLine->ddRVal = MapLegacyResult(ScanData.ddRVal); return dwRet; DeviceLost: { 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; } } return DDHAL_DRIVER_HANDLED; } /*****************************Private*Routine******************************\ * DdSetExclusiveMode * * History: * 22-Apr-1998 -by- John Stephens [johnstep] * Wrote it. \**************************************************************************/ #undef DPF_MODNAME #define DPF_MODNAME "DdSetExclusiveMode" DWORD APIENTRY DdSetExclusiveMode( PD3D8_SETEXCLUSIVEMODEDATA pSetExclusiveMode ) { DDHAL_SETEXCLUSIVEMODEDATA ExclusiveData; DWORD dwRet; // smac: How should lost devices behave? CheckForDeviceLost(pSetExclusiveMode->hDD); ZeroMemory(&ExclusiveData, sizeof(ExclusiveData)); ExclusiveData.dwEnterExcl = pSetExclusiveMode->dwEnterExcl; dwRet = OsThunkDdSetExclusiveMode( DDHANDLE(pSetExclusiveMode->hDD), (PDD_SETEXCLUSIVEMODEDATA) &ExclusiveData); pSetExclusiveMode->ddRVal = MapLegacyResult(ExclusiveData.ddRVal); return dwRet; } /*****************************Private*Routine******************************\ * DdFlipToGDISurface * * History: * 22-Apr-1998 -by- John Stephens [johnstep] * Wrote it. \**************************************************************************/ #undef DPF_MODNAME #define DPF_MODNAME "DdFlipToGDISurface" DWORD APIENTRY DdFlipToGDISurface( PD3D8_FLIPTOGDISURFACEDATA pFlipToGDISurface ) { DDHAL_FLIPTOGDISURFACEDATA FlipData; DWORD dwRet; // smac: How should lost devices behave? CheckForDeviceLost(pFlipToGDISurface->hDD); FlipData.dwToGDI = pFlipToGDISurface->dwToGDI; FlipData.dwReserved = 0; FlipData.ddRVal = E_FAIL; dwRet = OsThunkDdFlipToGDISurface( DDHANDLE(pFlipToGDISurface->hDD), (PDD_FLIPTOGDISURFACEDATA) &FlipData); if (DDHAL_DRIVER_HANDLED == dwRet) pFlipToGDISurface->ddRVal = FlipData.ddRVal; pFlipToGDISurface->ddRVal = MapLegacyResult(pFlipToGDISurface->ddRVal); return dwRet; } /*****************************Private*Routine******************************\ * DdGetAvailDriverMemory * * History: * 16-Feb-1997 -by- J. Andrew Goossen [andrewgo] * Wrote it. \**************************************************************************/ #undef DPF_MODNAME #define DPF_MODNAME "DdGetAvailDriverMemory" DWORD APIENTRY DdGetAvailDriverMemory( PD3D8_GETAVAILDRIVERMEMORYDATA pGetAvailDriverMemory ) { DDHAL_GETAVAILDRIVERMEMORYDATA MemoryData; DWORD dwRet; // smac: How should lost devices behave? CheckForDeviceLost(pGetAvailDriverMemory->hDD); pGetAvailDriverMemory->dwFree = 0; // Convert the pool to something that the driver can understand memset(&MemoryData, 0, sizeof(MemoryData)); switch (pGetAvailDriverMemory->Pool) { case D3DPOOL_LOCALVIDMEM: MemoryData.DDSCaps.dwCaps |= DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY; break; case D3DPOOL_DEFAULT: MemoryData.DDSCaps.dwCaps |= DDSCAPS_VIDEOMEMORY; break; case D3DPOOL_NONLOCALVIDMEM: MemoryData.DDSCaps.dwCaps |= DDSCAPS_NONLOCALVIDMEM | DDSCAPS_VIDEOMEMORY; break; default: return DDHAL_DRIVER_HANDLED; } if (pGetAvailDriverMemory->dwUsage & D3DUSAGE_DEPTHSTENCIL) { MemoryData.DDSCaps.dwCaps |= DDSCAPS_ZBUFFER; } if (pGetAvailDriverMemory->dwUsage & D3DUSAGE_RENDERTARGET) { MemoryData.DDSCaps.dwCaps |= DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE; } if (pGetAvailDriverMemory->dwUsage & D3DUSAGE_TEXTURE) { MemoryData.DDSCaps.dwCaps |= DDSCAPS_TEXTURE; } dwRet = OsThunkDdGetAvailDriverMemory( DDHANDLE(pGetAvailDriverMemory->hDD), (PDD_GETAVAILDRIVERMEMORYDATA) &MemoryData); pGetAvailDriverMemory->dwFree = MemoryData.dwFree; return dwRet; } /*****************************Private*Routine******************************\ * D3D8QueryDirectDrawObject * * History: * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo] * Wrote it. \**************************************************************************/ #undef DPF_MODNAME #define DPF_MODNAME "D3D8QueryDirectDrawObject" BOOL APIENTRY 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 ) { PDDDEVICEHANDLE pDevice = (PDDDEVICEHANDLE) hDD; DD_HALINFO HalInfo; DWORD adwCallBackFlags[3]; DWORD dwFlags; VIDEOMEMORY* pVideoMemoryList; VIDEOMEMORY* pVideoMemory; DWORD dwNumHeaps; DWORD dwNumFourCC; D3DNTHAL_CALLBACKS D3dCallbacks; D3DNTHAL_GLOBALDRIVERDATA D3dDriverData; DD_D3DBUFCALLBACKS D3dBufferCallbacks; DDSCAPSEX SurfCapsEx; DD_GETDRIVERINFODATA GetDriverInfoData; DWORD dwSize; DD_MORESURFACECAPS * pSurfCaps; DWORD dwRet; DWORD i; DD_MISCELLANEOUSCALLBACKS MiscCallbacks; DD_MISCELLANEOUS2CALLBACKS Misc2Callbacks; D3DNTHAL_CALLBACKS3 D3dCallbacks3; D3DDISPLAYMODE Mode; UINT MaxZStencilFormats; UINT MaxTextureFormats; DDASSERT(pcTextureFormats); DDASSERT(pcZStencilFormats); MaxTextureFormats = *pcTextureFormats; MaxZStencilFormats = *pcZStencilFormats; *pcTextureFormats=0; *pcZStencilFormats=0; // memset the extended caps and global driver data ZeroMemory( pExtendedCaps, sizeof( *pExtendedCaps ) ); ZeroMemory( pGblDriverData, sizeof( *pGblDriverData ) ); ZeroMemory( &D3dDriverData, sizeof( D3dDriverData ) ); // smac: How should lost devices behave? CheckForDeviceLost(hDD); // Get all of the neccesary caps // Note: do this memset before the Query, since the caller might (ok will) be // using a ptr internal to this struct to hold a reference to the memset(pDriverCaps, 0, sizeof(D3D8_DRIVERCAPS)); // Behavior change: This code used to query for the supported texture format // list if the device is not software only and the caller supplied a non-NULL // buffer for the supported texture formats. Now, however, we never request // texture formats at this point. We only request them if we need to, that // is if the driver turns out to be a DirectX 7.0 driver or if it is a // DirectX 8.0 driver that doesn't support the new format querying mechanism. // This later clause is temporary only. Prior to RTM we will require // DirectX 8.0 drivers to support the new format querying mechanism. if (!OsThunkDdQueryDirectDrawObject(DDHANDLE(hDD), &HalInfo, &adwCallBackFlags[0], &D3dCallbacks, &D3dDriverData, &D3dBufferCallbacks, NULL, &dwNumHeaps, NULL, &dwNumFourCC, NULL)) { return(FALSE); } if ((!(HalInfo.dwFlags & DDHALINFO_GETDRIVERINFO2)) && (!(IS_SOFTWARE_DRIVER(pDevice))) && (NULL != pTextureFormats)) { // This is not a DirectX 8.0 or higher level driver so query again to get // the texture formats (as we know we won't get them through the new DirectX 8.0 // interfaces). if (!OsThunkDdQueryDirectDrawObject(DDHANDLE(hDD), &HalInfo, &adwCallBackFlags[0], &D3dCallbacks, &D3dDriverData, &D3dBufferCallbacks, pTextureFormats, &dwNumHeaps, NULL, &dwNumFourCC, NULL)) { return(FALSE); } } if (!IS_SOFTWARE_DRIVER(pDevice)) { // Initialize the texture format count from the driver data. // However, if this is a DX8 style driver this number will be // replaced by a format count reported by the new DX8 mechanism // code later in this function. *pcTextureFormats = D3dDriverData.dwNumTextureFormats; } // Display drivers can all render windowed if( (HalInfo.dwFlags & DDHALINFO_ISPRIMARYDISPLAY) || IsVGADevice(pDeviceName)) { HalInfo.ddCaps.dwCaps2 |= DDCAPS2_CANRENDERWINDOWED; } pDriverCaps->D3DCaps.Caps = HalInfo.ddCaps.dwCaps; pDriverCaps->D3DCaps.Caps2 = HalInfo.ddCaps.dwCaps2; pDriverCaps->D3DCaps.Caps3 = HalInfo.ddCaps.dwSVCaps; pDriverCaps->SVBCaps = HalInfo.ddCaps.dwSVBCaps; pDriverCaps->VSBCaps = HalInfo.ddCaps.dwVSBCaps; pDriverCaps->SVBCaps2 = HalInfo.ddCaps.dwSVBCaps2; pDevice->DisplayPitch = HalInfo.vmiData.lDisplayPitch; // Get the extended surface caps SurfCapsEx.dwCaps2 = 0; SurfCapsEx.dwCaps3 = 0; SurfCapsEx.dwCaps4 = 0; memset(&GetDriverInfoData, 0, sizeof(GetDriverInfoData)); GetDriverInfoData.dwSize = sizeof(GetDriverInfoData); GetDriverInfoData.guidInfo = GUID_DDMoreSurfaceCaps; dwSize = sizeof(DD_MORESURFACECAPS) + ((dwNumHeaps ? dwNumHeaps - 1 : 0) * sizeof(DDSCAPSEX) * 2); pSurfCaps = (DD_MORESURFACECAPS*) MemAlloc(dwSize); GetDriverInfoData.ddRVal = E_FAIL; if (pSurfCaps != NULL) { pSurfCaps->dwSize = dwSize; GetDriverInfoData.dwExpectedSize = dwSize; GetDriverInfoData.lpvData = pSurfCaps; dwRet = OsThunkDdGetDriverInfo(DDHANDLE(hDD), &GetDriverInfoData); if ((dwRet == DDHAL_DRIVER_HANDLED) && (GetDriverInfoData.ddRVal == S_OK)) { SurfCapsEx = pSurfCaps->ddsCapsMore; } MemFree(pSurfCaps); } // If the driver supports the "GetDriverInfo2" usage of GetDriverInfo then // use that now to get the D3DCAPS8. if ((HalInfo.dwFlags & DDHALINFO_GETDRIVERINFO2) && !IS_SOFTWARE_DRIVER(pDevice)) { // This buffer is used to pass information down to the driver and get // information back from the driver. The GetDriverInfo2 header and // any additional information to pass to the driver is copied into this // buffer prior to calling GetDriverInfo2. After the call the information // returned by the driver is contained in this buffer. All information // passed to and from the driver must fit within a buffer of this size. DWORD buffer[MAX_GDI2_BUFFER_DWORD_SIZE]; DD_GETDRIVERINFO2DATA* pgdi2; DD_GETFORMATCOUNTDATA* pgfcd; DD_GETFORMATDATA* pgfd; DD_DXVERSION* pDXVersion; int i; // Set up the DXVersion call memset(&buffer, 0, sizeof(buffer)); pDXVersion = (DD_DXVERSION *)buffer; // Before we do anything else, we notify the // driver about the DX version information. We ignore // errors here. pDXVersion->gdi2.dwReserved = sizeof(DD_STEREOMODE); pDXVersion->gdi2.dwMagic = D3DGDI2_MAGIC; pDXVersion->gdi2.dwType = D3DGDI2_TYPE_DXVERSION; pDXVersion->gdi2.dwExpectedSize = sizeof(DD_DXVERSION); pDXVersion->dwDXVersion = DD_RUNTIME_VERSION; memset(&GetDriverInfoData, 0, sizeof(GetDriverInfoData)); GetDriverInfoData.dwSize = sizeof(GetDriverInfoData); GetDriverInfoData.guidInfo = GUID_GetDriverInfo2; GetDriverInfoData.lpvData = &buffer; GetDriverInfoData.dwExpectedSize = sizeof(DD_STEREOMODE); dwRet = OsThunkDdGetDriverInfo(DDHANDLE(hDD), &GetDriverInfoData); if (dwRet != DDHAL_DRIVER_HANDLED || GetDriverInfoData.ddRVal != S_OK) { // Errors are ignored here dwRet = DDHAL_DRIVER_HANDLED; } memset(&buffer, 0, sizeof(buffer)); pgdi2 = (DD_GETDRIVERINFO2DATA*)&buffer; // 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(DD_STEREOMODE); 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 = &buffer; GetDriverInfoData.dwExpectedSize = sizeof(DD_STEREOMODE); dwRet = OsThunkDdGetDriverInfo(DDHANDLE(hDD), &GetDriverInfoData); if ((dwRet == DDHAL_DRIVER_HANDLED) && (GetDriverInfoData.ddRVal == S_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))"); return(FALSE); } // All went well. Copy the caps data across memcpy(&pDriverCaps->D3DCaps, &buffer, sizeof(D3DCAPS8)); // Drivers may not set the ddraw caps correctly, or they might not update them // across mode changes, so use the caps that we already have. pDriverCaps->D3DCaps.Caps = HalInfo.ddCaps.dwCaps; // Display drivers can all render windowed if( (HalInfo.dwFlags & DDHALINFO_ISPRIMARYDISPLAY) || IsVGADevice(pDeviceName)) { pDriverCaps->D3DCaps.Caps2 |= DDCAPS2_CANRENDERWINDOWED; } // Set the flag indicating that the DDI successfully reported DX8 // style caps pDriverCaps->dwFlags |= DDIFLAG_D3DCAPS8; // See device can do sub volume lock for volume texture. if (pDriverCaps->D3DCaps.DevCaps & D3DDEVCAPS_SUBVOLUMELOCK) { pDevice->dwFlags |= DDDEVICE_SUPPORTSUBVOLUMELOCK; } } // If this is a DX8 driver it needs to report it supported texture formats to us // using GetDriverInfo2. This is done in two stages, one query to determine the // number of supported formats, and one to actually retrieve those formats // iteratively. // 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(&buffer, 0, sizeof(buffer)); pgfcd = (DD_GETFORMATCOUNTDATA*)&buffer; pgfcd->gdi2.dwReserved = sizeof(DD_STEREOMODE); pgfcd->gdi2.dwMagic = D3DGDI2_MAGIC; pgfcd->gdi2.dwType = D3DGDI2_TYPE_GETFORMATCOUNT; pgfcd->gdi2.dwExpectedSize = sizeof(DD_GETFORMATCOUNTDATA); #if DBG // Ensure the driver actually sets the format count if it succeeds this call pgfcd->dwFormatCount = BOGUS_FIELD_VALUE; #endif // DBG memset(&GetDriverInfoData, 0, sizeof(GetDriverInfoData)); GetDriverInfoData.dwSize = sizeof(GetDriverInfoData); GetDriverInfoData.guidInfo = GUID_GetDriverInfo2; GetDriverInfoData.lpvData = &buffer; GetDriverInfoData.dwExpectedSize = sizeof(DD_STEREOMODE); dwRet = OsThunkDdGetDriverInfo(DDHANDLE(hDD), &GetDriverInfoData); if ((dwRet == DDHAL_DRIVER_HANDLED) && (GetDriverInfoData.ddRVal == S_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))"); return(FALSE); } #ifdef DBG if (BOGUS_FIELD_VALUE == ((DD_GETFORMATCOUNTDATA*)&buffer)->dwFormatCount) { DPF_ERR( "Driver succeeded GETFORMATCOUNT request but didn't set dwFormatCount. Driver error." ); 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 = ((DD_GETFORMATCOUNTDATA*)&buffer)->dwFormatCount; // 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; *pcTextureFormats = min(MaxTextureFormats, *pcTextureFormats); 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(&buffer, 0, sizeof(DD_GETFORMATDATA)); pgfd = (DD_GETFORMATDATA*)&buffer; pgfd->gdi2.dwReserved = sizeof(DD_STEREOMODE); pgfd->gdi2.dwMagic = D3DGDI2_MAGIC; pgfd->gdi2.dwType = D3DGDI2_TYPE_GETFORMAT; pgfd->gdi2.dwExpectedSize = sizeof(DD_GETFORMATDATA); pgfd->dwFormatIndex = c; #if DBG // Ensure the driver actually sets the format count if it succeeds this call pgfd->format.dwSize = BOGUS_FIELD_VALUE; #endif // DBG memset(&GetDriverInfoData, 0, sizeof(GetDriverInfoData)); GetDriverInfoData.dwSize = sizeof(GetDriverInfoData); GetDriverInfoData.guidInfo = GUID_GetDriverInfo2; GetDriverInfoData.lpvData = &buffer; GetDriverInfoData.dwExpectedSize = sizeof(DD_STEREOMODE); dwRet = OsThunkDdGetDriverInfo(DDHANDLE(hDD), &GetDriverInfoData); if ((dwRet == DDHAL_DRIVER_HANDLED) && (GetDriverInfoData.ddRVal == S_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))"); return(FALSE); } DDASSERT(c == ((DD_GETFORMATDATA*)&buffer)->dwFormatIndex); #ifdef DBG if (BOGUS_FIELD_VALUE == (((DD_GETFORMATDATA*)&buffer)->format).dwSize) { DPF_ERR( "Driver succeeded GETFORMAT request but didn't set format. Driver error." ); return(FALSE); } #endif // DBG // Looks like all went well. Initialize the surface description part of the format // list 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, &(((DD_GETFORMATDATA*)&buffer)->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" ); // This is a DirectX 8.0 level driver but it doesn't appear to support the // new DirectX 8.0 style format querying mechanism so query the kernel // again for the DirectX 7.0 style capabilities and use them instead. // Note, this is a temporary measure only, prior to the RTM of DirectX 8.0 // this fallback will be removed and drivers will be required to support // the new DirectX 8.0 style format reporting mechanism if ((!IS_SOFTWARE_DRIVER(pDevice)) && (NULL != pTextureFormats)) { if (!OsThunkDdQueryDirectDrawObject(DDHANDLE(hDD), &HalInfo, &adwCallBackFlags[0], &D3dCallbacks, &D3dDriverData, &D3dBufferCallbacks, pTextureFormats, &dwNumHeaps, NULL, &dwNumFourCC, NULL)) { return(FALSE); } } } } else if (D3dCallbacks.dwSize != 0 && D3dDriverData.dwSize != 0) { pGblDriverData->dwSize = D3dDriverData.dwSize; //watcha gonna do: DDASSERT(sizeof(pGblDriverData->hwCaps) == sizeof(D3dDriverData.hwCaps)); memcpy(&pGblDriverData->hwCaps, &D3dDriverData.hwCaps, sizeof(pGblDriverData->hwCaps)); pGblDriverData->dwNumVertices = D3dDriverData.dwNumVertices; pGblDriverData->dwNumClipVertices = D3dDriverData.dwNumClipVertices; // Get the D3D extended caps GetDriverInfoData.guidInfo = GUID_D3DExtendedCaps; GetDriverInfoData.ddRVal = E_FAIL; GetDriverInfoData.dwExpectedSize = sizeof(D3DHAL_D3DEXTENDEDCAPS); GetDriverInfoData.lpvData = pExtendedCaps; dwRet = OsThunkDdGetDriverInfo(DDHANDLE(hDD), &GetDriverInfoData); if ((dwRet != DDHAL_DRIVER_HANDLED) || (GetDriverInfoData.ddRVal != S_OK)) { DPF_ERR( "Get EXTENDEDCAPS from the driver failed" ); return FALSE; } } // Get the supported Z formats. We only do this if we are not using a // software driver if (!IS_SOFTWARE_DRIVER(pDevice)) { DWORD tempbuf[249]; // make this <1K bytes or GetDriverInfo() fails cuz it cant do its "expected size overwrite" test within its own 1K tempbuffer GetDriverInfoData.guidInfo = GUID_ZPixelFormats; GetDriverInfoData.ddRVal = E_FAIL; GetDriverInfoData.dwExpectedSize = sizeof(tempbuf); GetDriverInfoData.lpvData = tempbuf; dwRet = OsThunkDdGetDriverInfo(DDHANDLE(hDD), &GetDriverInfoData); if ((dwRet != DDHAL_DRIVER_HANDLED) || (GetDriverInfoData.ddRVal != S_OK) || ((GetDriverInfoData.dwActualSize-sizeof(DWORD)) % sizeof(DDPIXELFORMAT) != 0) || ((tempbuf[0]*sizeof(DDPIXELFORMAT)+sizeof(DWORD))>sizeof(tempbuf))) { // It could be that this is an old driver that doesn't support // stencil. We might be able to get some info from the global // driver data. if (pGblDriverData->hwCaps.dwDeviceZBufferBitDepth & DDBD_16) { (*pcZStencilFormats)++; if (pZStencilFormats && (*pcZStencilFormats <= MaxZStencilFormats)) { 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 && (*pcZStencilFormats <= MaxZStencilFormats)) { pZStencilFormats->dwSize = sizeof(DDPIXELFORMAT); pZStencilFormats->dwFlags = DDPF_ZBUFFER; pZStencilFormats->dwZBufferBitDepth = 32; pZStencilFormats->dwStencilBitDepth = 0; pZStencilFormats->dwZBitMask = 0xffffffff; pZStencilFormats->dwStencilBitMask = 0x00000000; pZStencilFormats++; } } } else { //We have a GetDriverInfo response to our Z format query. These are //DDPIXELFORMATs that we can copy back to our caller (*pcZStencilFormats) = tempbuf[0]; if(pZStencilFormats) { MaxZStencilFormats = min(MaxZStencilFormats, tempbuf[0]); memcpy(pZStencilFormats, &tempbuf[1], MaxZStencilFormats * sizeof(DDPIXELFORMAT)); } } } // Get info about the current mode D3D8GetMode (NULL, pDeviceName, &Mode, 0); pDevice->DisplayFormatWithAlpha = Mode.Format; pDevice->DisplayFormatWithoutAlpha = Mode.Format; if (Mode.Format == D3DFMT_X8R8G8B8) { if (HalInfo.vmiData.ddpfDisplay.dwFlags & DDPF_ALPHAPIXELS) { pDevice->DisplayFormatWithAlpha = D3DFMT_A8R8G8B8; } } if (Mode.Format == D3DFMT_X1R5G5B5) { if (HalInfo.vmiData.ddpfDisplay.dwFlags & DDPF_ALPHAPIXELS) { pDevice->DisplayFormatWithAlpha = D3DFMT_A1R5G5B5; } } pDriverCaps->DisplayWidth = Mode.Width; pDriverCaps->DisplayHeight = Mode.Height; pDriverCaps->DisplayFrequency = Mode.RefreshRate; pDriverCaps->DisplayFormatWithoutAlpha = Mode.Format; pDriverCaps->DisplayFormatWithAlpha = pDevice->DisplayFormatWithAlpha; // Get the Miscellaneous callbacks GetDriverInfoData.guidInfo = GUID_MiscellaneousCallbacks; GetDriverInfoData.ddRVal = E_FAIL; GetDriverInfoData.dwExpectedSize = sizeof(DD_MISCELLANEOUSCALLBACKS); GetDriverInfoData.lpvData = &MiscCallbacks; dwRet = OsThunkDdGetDriverInfo(DDHANDLE(hDD), &GetDriverInfoData); if ((dwRet != DDHAL_DRIVER_HANDLED) || (GetDriverInfoData.ddRVal != S_OK)) { memset (&MiscCallbacks, 0, sizeof(DD_MISCELLANEOUSCALLBACKS)); } // Get the Miscellaneous2 callbacks GetDriverInfoData.guidInfo = GUID_Miscellaneous2Callbacks; GetDriverInfoData.ddRVal = E_FAIL; GetDriverInfoData.dwExpectedSize = sizeof(DD_MISCELLANEOUS2CALLBACKS); GetDriverInfoData.lpvData = &Misc2Callbacks; dwRet = OsThunkDdGetDriverInfo(DDHANDLE(hDD), &GetDriverInfoData); if ((dwRet != DDHAL_DRIVER_HANDLED) || (GetDriverInfoData.ddRVal != S_OK)) { memset (&Misc2Callbacks, 0, sizeof(DD_MISCELLANEOUS2CALLBACKS)); } // Get the D3Dcallbacks3 callbacks GetDriverInfoData.guidInfo = GUID_D3DCallbacks3; GetDriverInfoData.ddRVal = E_FAIL; GetDriverInfoData.dwExpectedSize = sizeof(D3DNTHAL_CALLBACKS3); GetDriverInfoData.lpvData = &D3dCallbacks3; dwRet = OsThunkDdGetDriverInfo(DDHANDLE(hDD), &GetDriverInfoData); if ((dwRet != DDHAL_DRIVER_HANDLED) || (GetDriverInfoData.ddRVal != S_OK)) { memset (&D3dCallbacks3, 0, sizeof(D3DNTHAL_CALLBACKS3)); } // 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; if (D3dCallbacks.ContextCreate != NULL) { pCallbacks->CreateContext = D3dContextCreate; } if (D3dCallbacks.ContextDestroy != NULL) { pCallbacks->ContextDestroy = D3dContextDestroy; } if (D3dCallbacks.ContextDestroyAll != NULL) { pCallbacks->ContextDestroyAll = D3dContextDestroyAll; } if (Misc2Callbacks.GetDriverState) { pCallbacks->GetDriverState = DdGetDriverState; } if (D3dCallbacks3.ValidateTextureStageState != NULL) { pCallbacks->ValidateTextureStageState = D3dValidateTextureStageState; } if (D3dCallbacks3.DrawPrimitives2 != NULL) { pCallbacks->DrawPrimitives2 = D3dDrawPrimitives2; } if (HalInfo.dwFlags & DDHALINFO_GETDRIVERINFO2) { pDevice->dwFlags |= DDDEVICE_GETDRIVERINFO2; if (!(pDevice->dwFlags & DDDEVICE_INITIALIZED)) { // Since this is the first time we have seen this device, we need // to tell the driver that the runtime will send the propoer AGP // notification. InformDriverAGPWorkaroundAware((HANDLE) pDevice); } } pDevice->dwFlags |= DDDEVICE_INITIALIZED; if (FAILED(GetNTDeviceRect(pDeviceName,&pDevice->rcMonitor))) { SetRect(&pDevice->rcMonitor,0,0, GetSystemMetrics(SM_CXSCREEN),GetSystemMetrics(SM_CYSCREEN)); } // What about HW cursor support? check Must be done before SoftwareRast // Caps Overrides if (0 == pDriverCaps->D3DCaps.MaxStreams) { // 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; } } } // need to save a HAL copy in thunklayer, for example DdBlt needs caps pDevice->DDCaps = pDriverCaps->D3DCaps.Caps; pDevice->SVBCaps = pDriverCaps->SVBCaps; // 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 ); } pDevice->DriverLevel = 0; if (pDriverCaps->D3DCaps.MaxStreams != 0) { pDevice->DriverLevel = 8; } else if (pCallbacks->DrawPrimitives2 != NULL) { pDevice->DriverLevel = 7; } // Determine what version of windows is running so we can know // what lock parameters to send. Whistler is version 5.1. pDevice->bIsWhistler = IsWhistler(); // 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; } } if (NULL != HalInfo.lpD3DBufCallbacks ) { pDevice->dwFlags |= DDDEVICE_SUPPORTD3DBUF; } else { pDevice->dwFlags &= ~DDDEVICE_SUPPORTD3DBUF; } return(TRUE); } // // See NT bug 448720... // // AGP surfaces will be unlocked by the kernel mode in response to mode switches. // App may still be writing to surface. // Driver should therefore defer free of AGP memory until later. // "Later" is defined as when the usermode determines the app is done writing and can tell // the driver so. // // Drivers need to know that the runtime can do this so they can turn off any other workarounds // they might have. // /*****************************Private*Routine******************************\ * GetDriverInfo2 * * History: * 06-Nov-2001 maxmcm Wrote it \**************************************************************************/ #undef DPF_MODNAME #define DPF_MODNAME "GetDriverInfo2" DWORD APIENTRY GetDriverInfo2( DWORD* pdwDrvRet, HANDLE hDriver, DWORD dwType, DWORD dwSize, void* pBuffer) { DD_GETDRIVERINFO2DATA* pGDI2Data; DD_GETDRIVERINFODATA GetDriverInfoData; DWORD dwRet; PDDDEVICEHANDLE pDevice; // In some cases (e.g. ProfileAdapter), it is possible that we can get // here with a NULL device, so we should check for that. pDevice = (PDDDEVICEHANDLE) hDriver; if (pDevice == NULL) { *pdwDrvRet = E_FAIL; return DDHAL_DRIVER_HANDLED; } // Don't call the driver if they don't support GETDRIVERINFO2 if (!(pDevice->dwFlags & DDDEVICE_GETDRIVERINFO2)) { *pdwDrvRet = E_FAIL; return DDHAL_DRIVER_HANDLED; } // Setup GetDriverInfo2 call pGDI2Data = (DD_GETDRIVERINFO2DATA*) pBuffer; memset(pGDI2Data, 0, sizeof(*pGDI2Data)); pGDI2Data->dwReserved = sizeof(DD_STEREOMODE); pGDI2Data->dwMagic = D3DGDI2_MAGIC; pGDI2Data->dwType = dwType; pGDI2Data->dwExpectedSize = dwSize; memset(&GetDriverInfoData, 0, sizeof(GetDriverInfoData)); GetDriverInfoData.dwSize = sizeof(GetDriverInfoData); GetDriverInfoData.guidInfo = GUID_GetDriverInfo2; GetDriverInfoData.lpvData = pGDI2Data; GetDriverInfoData.dwExpectedSize = sizeof(DD_STEREOMODE); // Ask the driver for information dwRet = OsThunkDdGetDriverInfo(DDHANDLE(pDevice), &GetDriverInfoData); *pdwDrvRet = GetDriverInfoData.ddRVal; return dwRet; } void InformDriverAGPWorkaroundAware(HANDLE hDD) { DDNT_DEFERRED_AGP_AWARE_DATA aad; DWORD dwDrvRet; DWORD dwGDI2Ret; dwGDI2Ret = GetDriverInfo2(&dwDrvRet, hDD, _NT_D3DGDI2_TYPE_DEFERRED_AGP_AWARE, sizeof(aad), &aad); //drop the return code on the floor.... just a notification } void InformDriverFreeAGP(HANDLE hDD) { DDNT_FREE_DEFERRED_AGP_DATA fad; DWORD dwDrvRet; DWORD dwGDI2Ret; fad.dwProcessId = GetCurrentProcessId(); dwGDI2Ret = GetDriverInfo2(&dwDrvRet, hDD, _NT_D3DGDI2_TYPE_FREE_DEFERRED_AGP, sizeof(fad), &fad); //drop the return code on the floor.... just a notification } void InformDriverToDeferFrees(HANDLE hDD) { DDNT_FREE_DEFERRED_AGP_DATA fad; DWORD dwDrvRet; DWORD dwGDI2Ret; fad.dwProcessId = GetCurrentProcessId(); dwGDI2Ret = GetDriverInfo2(&dwDrvRet, hDD, _NT_D3DGDI2_TYPE_DEFER_AGP_FREES, sizeof(fad), &fad); //drop the return code on the floor.... just a notification } /*****************************Private*Routine******************************\ * D3D8CreateDirectDrawObject * * Calls GDI32 to get the global DirectDraw handle. * * History: * 16-Nov-1999 -by- Scott MacDonald [smac] * Wrote it. \**************************************************************************/ #undef DPF_MODNAME #define DPF_MODNAME "D3D8CreateDirectDrawObject" VOID APIENTRY D3D8CreateDirectDrawObject( HDC hdc, char* szDeviceName, HANDLE* phDD, D3DDEVTYPE Type, HINSTANCE* phLibrary, VOID* pInitFunction ) { DDRAWI_DIRECTDRAW_GBL ddg; PDDDEVICEHANDLE pDeviceHandle; HKEY hKey = (HKEY) NULL; *phDD = NULL; ddg.hDD = 0; pDeviceHandle = NULL; DdCreateDirectDrawObject (&ddg, hdc); if (ddg.hDD != 0) { pDeviceHandle = MemAlloc (sizeof(DDDEVICEHANDLE)); if (pDeviceHandle != NULL) { pDeviceHandle->hDD = (HANDLE)ddg.hDD; *phDD = (HANDLE) pDeviceHandle; lstrcpy (pDeviceHandle->szDeviceName, szDeviceName); pDeviceHandle->DisplayUniqueness = DdQueryDisplaySettingsUniqueness(); pDeviceHandle->hLastWnd = NULL; pDeviceHandle->pClipList = NULL; pDeviceHandle->pOrigClipList = NULL; *phLibrary = NULL; pDeviceHandle->DeviceType = Type; if (Type == D3DDEVTYPE_REF) { *phLibrary = LoadLibrary (D3D8_REFRASTNAME); pDeviceHandle->pDD = SwDDICreateDirectDraw(); if (pDeviceHandle->pDD == NULL) { *phDD = NULL; } else { pDeviceHandle->hLibrary = *phLibrary; } } else if (Type == D3DDEVTYPE_SW) { pDeviceHandle->pDD = SwDDICreateDirectDraw(); if (pDeviceHandle->pDD == NULL) { *phDD = NULL; } else { pDeviceHandle->pSwInitFunction = pInitFunction; } } } } if (*phDD == NULL) { if (pDeviceHandle) { MemFree (pDeviceHandle); } if (ddg.hDD != 0) { OsThunkDdDeleteDirectDrawObject((HANDLE) ddg.hDD); } } else { // See if they want to explicitly enable/disable driver behavior if (!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); } NumDevices++; } } /*****************************Private*Routine******************************\ * D3D8DeleteDirectDrawObject * * Note that all associated surface objects must be deleted before the * DirectDrawObject can be deleted. * * History: * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo] * Wrote it. \**************************************************************************/ #undef DPF_MODNAME #define DPF_MODNAME "D3D8DeleteDirectDrawObject" VOID APIENTRY D3D8DeleteDirectDrawObject( HANDLE hDD ) { PDDDEVICEHANDLE pHandle = (PDDDEVICEHANDLE) hDD; PDEFERREDCREATE pTemp; NumDevices--; if (pHandle!= NULL) { PDEFERREDCREATE pDefCreate = pHandle->pDeferList; OsThunkDdDeleteDirectDrawObject(DDHANDLE(hDD)); if (NULL != pHandle->SurfaceHandleList.dwList) { MemFree(pHandle->SurfaceHandleList.dwList); } if (NULL != pHandle->pDD) { if ( NULL != pHandle->pDD->lpGbl->lpDDCBtmp) { MemFree(pHandle->pDD->lpGbl->lpDDCBtmp); } MemFree(pHandle->pDD); } if (NULL != pHandle->pClipList) { MemFree(pHandle->pClipList); } if (NULL != pHandle->pOrigClipList) { MemFree(pHandle->pOrigClipList); } #ifdef DEBUG // In debug print the types of objects // that weren't released if (pHandle->pSurfList != NULL) { PDDSURFHANDLE pSurf = pHandle->pSurfList; DPF_ERR("Not all objects were freed: the following indicate " "the types of unfreed objects."); while (pSurf) { DebugPrintSurfaceInfo(pSurf); pSurf = pSurf->pNext; } } #endif while (pDefCreate != NULL) { pTemp = pDefCreate->pNext; MemFree(pDefCreate->CreateData.pSList); MemFree(pDefCreate); pDefCreate = pTemp; } DDASSERT(pHandle->pSurfList == NULL); DDASSERT(pHandle->pContext == NULL); MemFree(hDD); } } /*****************************Private*Routine******************************\ * DdGetDC * * History: * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo] * Wrote it. \**************************************************************************/ #undef DPF_MODNAME #define DPF_MODNAME "D3D8GetDC" HDC APIENTRY D3D8GetDC( HANDLE hSurface, LPPALETTEENTRY pPalette ) { if (CheckForDeviceLost((HANDLE)((PDDSURFHANDLE)hSurface)->pDevice)) { return NULL; } return(OsThunkDdGetDC(GetSurfHandle(hSurface), pPalette)); } /*****************************Private*Routine******************************\ * DdReleaseDC * * History: * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo] * Wrote it. \**************************************************************************/ #undef DPF_MODNAME #define DPF_MODNAME "D3D8ReleaseDC" BOOL APIENTRY D3D8ReleaseDC( HANDLE hSurface, HDC hdc ) { DDASSERT(hdc != NULL); return(OsThunkDdReleaseDC(GetSurfHandle(hSurface))); } /*****************************Private*Routine******************************\ * DdReenableDirectDrawObject * * History: * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo] * Wrote it. \**************************************************************************/ #undef DPF_MODNAME #define DPF_MODNAME "D3D8ReenableDirectDrawObject" BOOL APIENTRY D3D8ReenableDirectDrawObject( HANDLE hDD, BOOL* pbNewMode ) { BOOL bRet; PDDDEVICEHANDLE pHandle = (PDDDEVICEHANDLE) hDD; bRet = OsThunkDdReenableDirectDrawObject(DDHANDLE(hDD), pbNewMode); if (!bRet && ((pHandle->DeviceType == D3DDEVTYPE_REF) || (pHandle->DeviceType == D3DDEVTYPE_SW)) && !(pHandle->DDCaps & ~DDCAPS_NOHARDWARE)) { bRet = TRUE; } return bRet; } /*****************************Private*Routine******************************\ * DdSetGammaRamp * * History: * 18-Oct-1997 -by- smac * Wrote it. \**************************************************************************/ #undef DPF_MODNAME #define DPF_MODNAME "D3D8SetGammaRamp" BOOL APIENTRY D3D8SetGammaRamp( HANDLE hDD, HDC hdc, LPVOID lpGammaRamp ) { if (CheckForDeviceLost(hDD)) { return TRUE; } return(OsThunkDdSetGammaRamp(DDHANDLE(hDD), hdc, lpGammaRamp)); } /*****************************Private*Routine******************************\ * D3D8BuildModeTable * * History: * 15-Dec-1999 -by- smac * Wrote it. \**************************************************************************/ #undef DPF_MODNAME #define DPF_MODNAME "D3D8BuildModeTable" VOID APIENTRY D3D8BuildModeTable( char* pszDevice, D3DDISPLAYMODE* pModeTable, DWORD* pNumEntries, D3DFORMAT Unknown16, HANDLE hProfile, BOOL b16bppSupported, BOOL b32bppSupported ) { int i; int j; DEVMODE dm; D3DFORMAT format; int NumTempEntries = 0; DWORD NumActualEntries = 0; dm.dmSize = sizeof(dm); for (i = 0; EnumDisplaySettings(pszDevice, i, &dm); ++i) { // Filter out all modes other than 15, 16 and 32bpp if ((dm.dmBitsPerPel != 15) && (dm.dmBitsPerPel != 16) && (dm.dmBitsPerPel != 32)) { continue; } if (((dm.dmBitsPerPel == 15) || (dm.dmBitsPerPel == 16)) && !b16bppSupported) { continue; } else if ((dm.dmBitsPerPel == 32) && !b32bppSupported) { continue; } // Make sure that we understand the format. if ((dm.dmBitsPerPel == 16) || (dm.dmBitsPerPel == 15)) { format = Unknown16; } else { DDASSERT(dm.dmBitsPerPel == 32); format = D3DFMT_X8R8G8B8; } if (pModeTable != NULL) { ///The caller must pass us a number DDASSERT( (*pNumEntries) ); if ( NumActualEntries >= (*pNumEntries) ) { //we exceeded the number of entries allocated for us. //tell the caller to re-query and try again. NumActualEntries = 0; break; } // Add the new mode. pModeTable[NumActualEntries].Width = dm.dmPelsWidth; pModeTable[NumActualEntries].Height = dm.dmPelsHeight; pModeTable[NumActualEntries].RefreshRate = dm.dmDisplayFrequency; pModeTable[NumActualEntries].Format = format; } NumActualEntries++; } //The caller will either pass a NULL modelist pointer, in which case //it is expecting us to fill in the number of entries. If the modelist // is non-null, the caller expects us to fill the table but not // overwrite. If we find the table has grown, ask the caller to // re-allocate by returning 0 modes. (*pNumEntries) = NumActualEntries; } /*****************************Private*Routine******************************\ * D3D8IsDeviceLost * * History: * 15-Dec-1999 -by- smac * Wrote it. \**************************************************************************/ #undef DPF_MODNAME #define DPF_MODNAME "D3D8IsDeviceLost" BOOL APIENTRY D3D8IsDeviceLost( HANDLE hDD ) { return CheckForDeviceLost(hDD); } /*****************************Private*Routine******************************\ * D3D8CanRestoreNow * 15-Dec-1999 -by- smac * Wrote it. \**************************************************************************/ #undef DPF_MODNAME #define DPF_MODNAME "D3D8CanRestoreNow" BOOL APIENTRY D3D8CanRestoreNow( HANDLE hDD ) { PDDDEVICEHANDLE pDeviceHandle = (PDDDEVICEHANDLE) hDD; BOOL bNewMode; D3D8_DRIVERCAPS DriverData; D3D8_GLOBALDRIVERDATA D3DGlobalDriverData; D3DHAL_D3DEXTENDEDCAPS D3DExtendedCaps; D3D8_CALLBACKS Callbacks; UINT uiDummy; // If we aren't lost, then it's an easy call if (!CheckForDeviceLost(hDD)) { return TRUE; } // Otherwise, we actually need to call the kernel and look at the caps memset(&DriverData, 0, sizeof(DriverData)); memset(&D3DGlobalDriverData, 0, sizeof(D3DGlobalDriverData)); memset(&D3DExtendedCaps, 0, sizeof(D3DExtendedCaps)); memset(&Callbacks, 0, sizeof(Callbacks)); if (!D3D8ReenableDirectDrawObject (hDD,&bNewMode) || !D3D8QueryDirectDrawObject(hDD, &DriverData, &Callbacks, pDeviceHandle->szDeviceName, pDeviceHandle->hLibrary, &D3DGlobalDriverData, &D3DExtendedCaps, NULL,NULL,&uiDummy,&uiDummy)) { return FALSE; } if (IS_SOFTWARE_DRIVER(hDD) || ((DriverData.D3DCaps.Caps & DDCAPS_3D) && (Callbacks.DrawPrimitives2 != NULL))) { return TRUE; } return FALSE; } /*****************************Private*Routine******************************\ * D3D8RestoreDevice * 15-Dec-1999 -by- smac * Wrote it. \**************************************************************************/ #undef DPF_MODNAME #define DPF_MODNAME "D3D8RestoreDevice" void APIENTRY D3D8RestoreDevice ( HANDLE hDD ) { HRESULT hr; DWORD i, j, k; DWORD Width, Height, Depth; BYTE *SliceSrc, *SliceDst, *RowSrc, *RowDst; PDDDEVICEHANDLE pDeviceHandle = (PDDDEVICEHANDLE) hDD; PDDSURFHANDLE pSurf; PD3DCONTEXTHANDLE pContext = pDeviceHandle->pContext; PDEFERREDCREATE pDefCreate = pDeviceHandle->pDeferList; PDEFERREDCREATE *ppNext = &pDeviceHandle->pDeferList; PDEFERREDCREATE pTemp; D3D8_LOCKDATA LockData; D3D8_UNLOCKDATA UnlockData; ULONG_PTR pVidmem[32 * 6]; // First, say that we aren't lost anymore pDeviceHandle->DisplayUniqueness = DdQueryDisplaySettingsUniqueness(); pDeviceHandle->bDeviceLost = FALSE; pDeviceHandle->dwFlags &= ~DDDEVICE_DP2ERROR; // Now, check for any sysmem surfaces that were created while // the device was lost and call CreateSurfaceEx if they need it. pSurf = pDeviceHandle->pSurfList; while (pSurf != NULL) { if ((pSurf->dwCookie != 0) && (pSurf->dwFlags & DDSURF_DEFERCREATEEX)) { hr = OsThunkDdCreateSurfaceEx( DDHANDLE(hDD), pSurf->hSurface, pSurf->dwCookie); if (SUCCEEDED(hr)) { pSurf->dwFlags &= ~DDSURF_DEFERCREATEEX; } else { // TODO: Handle error condition DPF(0, "CreateSurfaceEx failed when resurrecting sysmem or D3D managed surfaces"); } } pSurf = pSurf->pNext; } // Now, create the D3D context if we need to. if ((pContext != NULL) && (pContext->dwFlags & D3DCONTEXT_DEFERCREATE)) { D3D8_CONTEXTCREATEDATA ContextData; memset(&ContextData, 0, sizeof(ContextData)); ContextData.hDD = DDHANDLE(hDD); ContextData.dwPID = pContext->dwPID; ContextData.dwhContext = (ULONG_PTR) pContext->hDeferHandle; OsThunkD3dContextCreate(DDHANDLE(hDD), GetSurfHandle(pContext->pSurface), GetSurfHandle(pContext->pDDSZ), (D3DNTHAL_CONTEXTCREATEI *)&ContextData); if (SUCCEEDED(ContextData.ddrval)) { pContext->dwhContext = (HANDLE) ContextData.dwhContext; pContext->dwFlags &= ~D3DCONTEXT_DEFERCREATE; } else { // TODO: Handle error condition } } // Finally resurrect our deferred driver managed surfaces (Gulp!) while (pDefCreate != NULL) { DDASSERT(pDefCreate->CreateData.dwSCnt <= 32 * 6); // 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; } // Save off all the fpVidmems since they will be overwritten for (i = 0; i < pDefCreate->CreateData.dwSCnt; i++) { pSurf = (PDDSURFHANDLE) pDefCreate->CreateData.pSList[i].hKernelHandle; pVidmem[i] = pSurf->fpVidMem; } // Attempt to resurrect pDefCreate->CreateData.bReUse = TRUE; hr = DdCreateSurface(&pDefCreate->CreateData); if (SUCCEEDED(hr)) { for (i = 0; i < pDefCreate->CreateData.dwSCnt; i++) { pSurf = (PDDSURFHANDLE) pDefCreate->CreateData.pSList[i].hKernelHandle; // Reset DDSURF_SYSMEMALLOCATED to keep DdLock below happy pSurf->dwFlags &= ~DDSURF_SYSMEMALLOCATED; // Lock and copy ZeroMemory(&LockData, sizeof(LockData)); LockData.hDD = hDD; LockData.hSurface = pSurf; hr = DdLock(&LockData); if (SUCCEEDED(hr)) { SliceSrc = (BYTE*)pVidmem[i]; 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((VOID*)pVidmem[i]); } // 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 (pDeviceHandle->pDeferList != NULL) { // TODO: // Ummm, we were not able to resurrect. This may be due to out of memory // or if a mode switch happened as we were trying to Reset (ACK!). The // former probably needs to be reported to the app. The latter is // probably harmless, because the app will eventually realize this and // try again. DPF(0,"Unable to resurrect all driver managed surfaces."); } } /*****************************Private*Routine******************************\ * D3D8AreVidmemSurfaces * 15-Dec-1999 -by- smac * Wrote it. \**************************************************************************/ #undef DPF_MODNAME #define DPF_MODNAME "D3D8DoVidmemSurfacesExist " BOOL APIENTRY D3D8DoVidmemSurfacesExist ( HANDLE hDD ) { PDDDEVICEHANDLE pDeviceHandle = (PDDDEVICEHANDLE) hDD; PDDSURFHANDLE pSurf; // Walk the list and return TRUE is we find any surfaces that are either // local or nonlocal vidmem. pSurf = pDeviceHandle->pSurfList; while (pSurf != NULL) { if ((pSurf->Pool == D3DPOOL_LOCALVIDMEM) || (pSurf->Pool == D3DPOOL_NONLOCALVIDMEM) || (pSurf->dwFlags & DDSURF_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 & DDSURF_TREATASVIDMEM)) { DebugPrintSurfaceInfo(pSurf); } pSurf = pSurf->pNext; } #endif return TRUE; } pSurf = pSurf->pNext; } // Is this the first time that the device has become ready? if (!(pDeviceHandle->dwFlags & DDDEVICE_READY) && (pDeviceHandle->bDeviceLost)) { pDeviceHandle->dwFlags |= DDDEVICE_READY; if (++NumReadyDevices == NumDevices) { InformDriverFreeAGP(pDeviceHandle); } } return FALSE; } #undef DPF_MODNAME #define DPF_MODNAME "D3D8BeginProfile" HANDLE APIENTRY D3D8BeginProfile( char* pDeviceName) { return NULL; } #undef DPF_MODNAME #define DPF_MODNAME "D3D8EndProfile" void APIENTRY D3D8EndProfile( HANDLE Handle) { } DWORD APIENTRY D3D8SetCooperativeLevel( HANDLE hDD, HWND hWnd, DWORD dwFlags ) { return S_OK; } BOOL APIENTRY D3D8IsDummySurface( HANDLE hSurface ) { return FALSE; } VOID APIENTRY D3D8LoseDevice( HANDLE hDD ) { PDDDEVICEHANDLE pDeviceHandle = (PDDDEVICEHANDLE) hDD; PDDSURFHANDLE pSurf; if (!pDeviceHandle->bDeviceLost) { pDeviceHandle->bDeviceLost = TRUE; pSurf = pDeviceHandle->pSurfList; while (pSurf != NULL) { if (IS_SURFACE_LOOSABLE(pSurf)) { FreeSurfaceObject(pSurf); pSurf->fpVidMem = (ULONG_PTR) NULL; } pSurf = pSurf->pNext; } } }