mirror of https://github.com/tongzx/nt5src
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
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;
|
|
}
|
|
}
|
|
}
|
|
|