|
|
/******************************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 <ddrawint.h>
#include <d3dnthal.h>
#include <winddi.h>
#include <osthunk.h>
#include "ddithunk.h"
#include <d3d8sddi.h>
#include <assert.h>
#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
// <kd> 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; i<n; i++) { prectlD->left = 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; cnt<prd->rdh.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;cnt<prd->rdh.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; } } }
|