Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

6135 lines
238 KiB

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