mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-01-19 20:24:49 +00:00
GFX now handles non-default adapters
The GFX (DirectX) pipeline did not respect the choice of adapter and always went for the default one. Normally this isn't an issue unless you wish to target a particular adapter and display device combination. This has been corrected. The GFX initialize functions now attempt to find the best adapter that matches a given display device (i.e. monitor) if one has been passed in. To aid with choosing a display device some new monitor enumeration methods have been added to the platform window manager. These methods have been exposed to the Canvas.
This commit is contained in:
parent
1ed1a41256
commit
0d77cdc270
|
|
@ -30,9 +30,9 @@
|
|||
#endif
|
||||
|
||||
|
||||
GFXD3D9CardProfiler::GFXD3D9CardProfiler() : GFXCardProfiler()
|
||||
GFXD3D9CardProfiler::GFXD3D9CardProfiler(U32 adapterIndex) : GFXCardProfiler()
|
||||
{
|
||||
|
||||
mAdapterOrdinal = adapterIndex;
|
||||
}
|
||||
|
||||
GFXD3D9CardProfiler::~GFXD3D9CardProfiler()
|
||||
|
|
@ -133,7 +133,7 @@ bool GFXD3D9CardProfiler::_queryFormat( const GFXFormat fmt, const GFXTexturePro
|
|||
if(texFormat == (_D3DFORMAT)GFX_UNSUPPORTED_VAL)
|
||||
return false;
|
||||
|
||||
HRESULT hr = pD3D->CheckDeviceFormat( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
|
||||
HRESULT hr = pD3D->CheckDeviceFormat( mAdapterOrdinal, D3DDEVTYPE_HAL,
|
||||
adapterFormat, usage, rType, texFormat );
|
||||
|
||||
bool retVal = SUCCEEDED( hr );
|
||||
|
|
@ -145,7 +145,7 @@ bool GFXD3D9CardProfiler::_queryFormat( const GFXFormat fmt, const GFXTexturePro
|
|||
{
|
||||
usage ^= D3DUSAGE_AUTOGENMIPMAP;
|
||||
|
||||
hr = pD3D->CheckDeviceFormat( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
|
||||
hr = pD3D->CheckDeviceFormat( mAdapterOrdinal, D3DDEVTYPE_HAL,
|
||||
adapterFormat, usage, D3DRTYPE_TEXTURE, GFXD3D9TextureFormat[fmt] );
|
||||
|
||||
retVal = SUCCEEDED( hr );
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ private:
|
|||
UINT mAdapterOrdinal;
|
||||
|
||||
public:
|
||||
GFXD3D9CardProfiler();
|
||||
GFXD3D9CardProfiler(U32 adapterIndex);
|
||||
~GFXD3D9CardProfiler();
|
||||
void init();
|
||||
|
||||
|
|
|
|||
|
|
@ -265,6 +265,8 @@ public:
|
|||
|
||||
GFXAdapterType getAdapterType(){ return Direct3D9; }
|
||||
|
||||
U32 getAdaterIndex() const { return mAdapterIndex; }
|
||||
|
||||
virtual GFXCubemap *createCubemap();
|
||||
|
||||
virtual F32 getPixelShaderVersion() const { return mPixVersion; }
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ GFXD3D9OcclusionQuery::OcclusionQueryStatus GFXD3D9OcclusionQuery::getStatus( bo
|
|||
return Unset;
|
||||
|
||||
#ifdef TORQUE_GATHER_METRICS
|
||||
AssertFatal( mBeginFrame < GuiTSCtrl::getFrameCount(), "GFXD3D9OcclusionQuery::getStatus - called on the same frame as begin!" );
|
||||
//AssertFatal( mBeginFrame < GuiTSCtrl::getFrameCount(), "GFXD3D9OcclusionQuery::getStatus - called on the same frame as begin!" );
|
||||
|
||||
//U32 mTimeSinceEnd = mTimer->getElapsedMs();
|
||||
//AssertFatal( mTimeSinceEnd >= 5, "GFXD3DOcculsionQuery::getStatus - less than TickMs since called ::end!" );
|
||||
|
|
|
|||
|
|
@ -43,9 +43,10 @@ U32 GFXD3D9TextureObject::mTexCount = 0;
|
|||
//-----------------------------------------------------------------------------
|
||||
// Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
GFXD3D9TextureManager::GFXD3D9TextureManager( LPDIRECT3DDEVICE9 d3ddevice )
|
||||
GFXD3D9TextureManager::GFXD3D9TextureManager( LPDIRECT3DDEVICE9 d3ddevice, U32 adapterIndex )
|
||||
{
|
||||
mD3DDevice = d3ddevice;
|
||||
mAdapterIndex = adapterIndex;
|
||||
dMemset( mCurTexSet, 0, sizeof( mCurTexSet ) );
|
||||
mD3DDevice->GetDeviceCaps(&mDeviceCaps);
|
||||
}
|
||||
|
|
@ -183,7 +184,7 @@ void GFXD3D9TextureManager::_innerCreateTexture( GFXD3D9TextureObject *retTex,
|
|||
mslevel = antialiasLevel;
|
||||
#ifdef TORQUE_DEBUG
|
||||
DWORD MaxSampleQualities;
|
||||
d3d->getD3D()->CheckDeviceMultiSampleType(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, d3dTextureFormat, FALSE, D3DMULTISAMPLE_NONMASKABLE, &MaxSampleQualities);
|
||||
d3d->getD3D()->CheckDeviceMultiSampleType(mAdapterIndex, D3DDEVTYPE_HAL, d3dTextureFormat, FALSE, D3DMULTISAMPLE_NONMASKABLE, &MaxSampleQualities);
|
||||
AssertFatal(mslevel < MaxSampleQualities, "Invalid AA level!");
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,8 +36,10 @@ class GFXD3D9TextureManager : public GFXTextureManager
|
|||
{
|
||||
friend class GFXD3D9TextureObject;
|
||||
|
||||
U32 mAdapterIndex;
|
||||
|
||||
public:
|
||||
GFXD3D9TextureManager( LPDIRECT3DDEVICE9 d3ddevice );
|
||||
GFXD3D9TextureManager( LPDIRECT3DDEVICE9 d3ddevice, U32 adapterIndex );
|
||||
virtual ~GFXD3D9TextureManager();
|
||||
|
||||
protected:
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ GFXFormat GFXPCD3D9Device::selectSupportedFormat(GFXTextureProfile *profile,
|
|||
usage |= D3DUSAGE_QUERY_FILTER;
|
||||
|
||||
D3DDISPLAYMODE mode;
|
||||
D3D9Assert(mD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &mode), "Unable to get adapter mode.");
|
||||
D3D9Assert(mD3D->GetAdapterDisplayMode(mAdapterIndex, &mode), "Unable to get adapter mode.");
|
||||
|
||||
D3DRESOURCETYPE type;
|
||||
if(texture)
|
||||
|
|
@ -130,7 +130,7 @@ GFXFormat GFXPCD3D9Device::selectSupportedFormat(GFXTextureProfile *profile,
|
|||
|
||||
for(U32 i=0; i<formats.size(); i++)
|
||||
{
|
||||
if(mD3D->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, mode.Format,
|
||||
if(mD3D->CheckDeviceFormat(mAdapterIndex, D3DDEVTYPE_HAL, mode.Format,
|
||||
usage, type, GFXD3D9TextureFormat[formats[i]]) == D3D_OK)
|
||||
return formats[i];
|
||||
}
|
||||
|
|
@ -259,9 +259,12 @@ void GFXPCD3D9Device::enumerateAdapters( Vector<GFXAdapter*> &adapterList )
|
|||
D3DADAPTER_IDENTIFIER9 temp;
|
||||
d3d9->GetAdapterIdentifier( adapterIndex, NULL, &temp ); // The NULL is the flags which deal with WHQL
|
||||
|
||||
dStrcpy( toAdd->mName, temp.Description );
|
||||
dStrncpy(toAdd->mName, temp.Description, GFXAdapter::MaxAdapterNameLen);
|
||||
dStrncat(toAdd->mName, " (D3D9)", GFXAdapter::MaxAdapterNameLen);
|
||||
|
||||
// And the output display device name
|
||||
dStrncpy(toAdd->mOutputName, temp.DeviceName, GFXAdapter::MaxAdapterNameLen);
|
||||
|
||||
// Video mode enumeration.
|
||||
Vector<D3DFORMAT> formats( __FILE__, __LINE__ );
|
||||
formats.push_back( D3DFMT_R5G6B5 ); // D3DFMT_R5G6B5 - 16bit format
|
||||
|
|
@ -303,10 +306,10 @@ void GFXPCD3D9Device::enumerateVideoModes()
|
|||
|
||||
for( S32 i = 0; i < formats.size(); i++ )
|
||||
{
|
||||
for( U32 j = 0; j < mD3D->GetAdapterModeCount( D3DADAPTER_DEFAULT, formats[i] ); j++ )
|
||||
for( U32 j = 0; j < mD3D->GetAdapterModeCount( mAdapterIndex, formats[i] ); j++ )
|
||||
{
|
||||
D3DDISPLAYMODE mode;
|
||||
mD3D->EnumAdapterModes( D3DADAPTER_DEFAULT, formats[i], j, &mode );
|
||||
mD3D->EnumAdapterModes( mAdapterIndex, formats[i], j, &mode );
|
||||
|
||||
GFXVideoMode toAdd;
|
||||
|
||||
|
|
@ -392,7 +395,7 @@ void GFXPCD3D9Device::init( const GFXVideoMode &mode, PlatformWindow *window /*
|
|||
deviceFlags |= D3DCREATE_PUREDEVICE;
|
||||
#endif
|
||||
|
||||
hres = createDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, winHwnd, deviceFlags, &d3dpp);
|
||||
hres = createDevice( mAdapterIndex, D3DDEVTYPE_HAL, winHwnd, deviceFlags, &d3dpp);
|
||||
|
||||
if (FAILED(hres) && hres != D3DERR_OUTOFVIDEOMEMORY)
|
||||
{
|
||||
|
|
@ -403,7 +406,7 @@ void GFXPCD3D9Device::init( const GFXVideoMode &mode, PlatformWindow *window /*
|
|||
// try mixed mode
|
||||
deviceFlags &= (~D3DCREATE_HARDWARE_VERTEXPROCESSING);
|
||||
deviceFlags |= D3DCREATE_MIXED_VERTEXPROCESSING;
|
||||
hres = createDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
|
||||
hres = createDevice( mAdapterIndex, D3DDEVTYPE_HAL,
|
||||
winHwnd, deviceFlags,
|
||||
&d3dpp);
|
||||
|
||||
|
|
@ -413,7 +416,7 @@ void GFXPCD3D9Device::init( const GFXVideoMode &mode, PlatformWindow *window /*
|
|||
Con::errorf(" Failed to create mixed mode device, trying software device");
|
||||
deviceFlags &= (~D3DCREATE_MIXED_VERTEXPROCESSING);
|
||||
deviceFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
|
||||
hres = createDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
|
||||
hres = createDevice( mAdapterIndex, D3DDEVTYPE_HAL,
|
||||
winHwnd, deviceFlags,
|
||||
&d3dpp);
|
||||
|
||||
|
|
@ -446,7 +449,7 @@ void GFXPCD3D9Device::init( const GFXVideoMode &mode, PlatformWindow *window /*
|
|||
Con::printf(" Cur. D3DDevice ref count=%d", mD3DDevice->AddRef() - 1);
|
||||
mD3DDevice->Release();
|
||||
|
||||
mTextureManager = new GFXD3D9TextureManager( mD3DDevice );
|
||||
mTextureManager = new GFXD3D9TextureManager( mD3DDevice, mAdapterIndex );
|
||||
|
||||
// Now reacquire all the resources we trashed earlier
|
||||
reacquireDefaultPoolResources();
|
||||
|
|
@ -510,7 +513,7 @@ void GFXPCD3D9Device::init( const GFXVideoMode &mode, PlatformWindow *window /*
|
|||
|
||||
Con::printf( " Using Direct3D9Ex: %s", isD3D9Ex() ? "Yes" : "No" );
|
||||
|
||||
mCardProfiler = new GFXD3D9CardProfiler();
|
||||
mCardProfiler = new GFXD3D9CardProfiler(mAdapterIndex);
|
||||
mCardProfiler->init();
|
||||
|
||||
gScreenShot = new ScreenShotD3D;
|
||||
|
|
@ -956,7 +959,7 @@ void GFXPCD3D9Device::_validateMultisampleParams(D3DFORMAT format, D3DMULTISAMPL
|
|||
if (aatype != D3DMULTISAMPLE_NONE)
|
||||
{
|
||||
DWORD MaxSampleQualities;
|
||||
mD3D->CheckDeviceMultiSampleType(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, format, FALSE, D3DMULTISAMPLE_NONMASKABLE, &MaxSampleQualities);
|
||||
mD3D->CheckDeviceMultiSampleType(mAdapterIndex, D3DDEVTYPE_HAL, format, FALSE, D3DMULTISAMPLE_NONMASKABLE, &MaxSampleQualities);
|
||||
aatype = D3DMULTISAMPLE_NONMASKABLE;
|
||||
aalevel = getMin((U32)aalevel, (U32)MaxSampleQualities-1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -248,7 +248,7 @@ void GFXPCD3D9TextureTarget::activate()
|
|||
"GFXPCD3D9TextureTarget::activate() - Failed to get surface description!");
|
||||
D3DFORMAT depthFormat = desc.Format;
|
||||
|
||||
HRESULT hr = mDevice->getD3D()->CheckDepthStencilMatch( D3DADAPTER_DEFAULT,
|
||||
HRESULT hr = mDevice->getD3D()->CheckDepthStencilMatch( mDevice->getAdaterIndex(),
|
||||
D3DDEVTYPE_HAL,
|
||||
mDevice->mDisplayMode.Format,
|
||||
renderFormat,
|
||||
|
|
@ -542,7 +542,7 @@ void GFXPCD3D9WindowTarget::activate()
|
|||
"GFXPCD3D9TextureTarget::activate() - Failed to get surface description!");
|
||||
D3DFORMAT depthFormat = desc.Format;
|
||||
|
||||
HRESULT hr = mDevice->getD3D()->CheckDepthStencilMatch( D3DADAPTER_DEFAULT,
|
||||
HRESULT hr = mDevice->getD3D()->CheckDepthStencilMatch( mDevice->getAdaterIndex(),
|
||||
D3DDEVTYPE_HAL,
|
||||
mDevice->mDisplayMode.Format,
|
||||
renderFormat,
|
||||
|
|
|
|||
|
|
@ -47,6 +47,10 @@ public:
|
|||
|
||||
char mName[MaxAdapterNameLen];
|
||||
|
||||
/// The name of the display output device for the adapter, if any.
|
||||
/// For example under Windows, this could be: \\.\DISPLAY1
|
||||
char mOutputName[MaxAdapterNameLen];
|
||||
|
||||
/// List of available full-screen modes. Windows can be any size,
|
||||
/// so we do not enumerate them here.
|
||||
Vector<GFXVideoMode> mAvailableModes;
|
||||
|
|
@ -55,6 +59,7 @@ public:
|
|||
F32 mShaderModel;
|
||||
|
||||
const char * getName() const { return mName; }
|
||||
const char * getOutputName() const { return mOutputName; }
|
||||
GFXAdapterType mType;
|
||||
U32 mIndex;
|
||||
CreateDeviceInstanceDelegate mCreateDeviceInstanceDelegate;
|
||||
|
|
@ -64,6 +69,7 @@ public:
|
|||
VECTOR_SET_ASSOCIATION( mAvailableModes );
|
||||
|
||||
mName[0] = 0;
|
||||
mOutputName[0] = 0;
|
||||
mShaderModel = 0.f;
|
||||
mIndex = 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -156,35 +156,63 @@ void GFXInit::cleanup()
|
|||
SAFE_DELETE( smRegisterDeviceSignal );
|
||||
}
|
||||
|
||||
GFXAdapter* GFXInit::getAdapterOfType( GFXAdapterType type )
|
||||
bool GFXInit::compareAdapterOutputDevice(const GFXAdapter* adapter, const char* outputDevice)
|
||||
{
|
||||
GFXAdapter* adapter = NULL;
|
||||
// If the adapter doesn't have an output display device, then it supports all of them
|
||||
if(!adapter->mOutputName[0])
|
||||
return true;
|
||||
|
||||
// Try and match the first part of the output device display name. For example,
|
||||
// an adapter->mOutputName of "\\.\DISPLAY1" might correspond to a display name
|
||||
// of "\\.\DISPLAY1\Monitor0". If two monitors are set up in duplicate mode then
|
||||
// they will have the same 'display' part in their display name.
|
||||
return (dStrstr(outputDevice, adapter->mOutputName) == outputDevice);
|
||||
}
|
||||
|
||||
GFXAdapter* GFXInit::getAdapterOfType( GFXAdapterType type, const char* outputDevice )
|
||||
{
|
||||
bool testOutputDevice = false;
|
||||
if(outputDevice && outputDevice[0])
|
||||
testOutputDevice = true;
|
||||
|
||||
for( U32 i = 0; i < smAdapters.size(); i++ )
|
||||
{
|
||||
if( smAdapters[i]->mType == type )
|
||||
{
|
||||
adapter = smAdapters[i];
|
||||
break;
|
||||
if(testOutputDevice)
|
||||
{
|
||||
// Check if the output display device also matches
|
||||
if(compareAdapterOutputDevice(smAdapters[i], outputDevice))
|
||||
{
|
||||
return smAdapters[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// No need to also test the output display device, so return
|
||||
return smAdapters[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return adapter;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GFXAdapter* GFXInit::chooseAdapter( GFXAdapterType type)
|
||||
GFXAdapter* GFXInit::chooseAdapter( GFXAdapterType type, const char* outputDevice)
|
||||
{
|
||||
GFXAdapter* adapter = GFXInit::getAdapterOfType(type);
|
||||
GFXAdapter* adapter = GFXInit::getAdapterOfType(type, outputDevice);
|
||||
|
||||
if(!adapter && type != OpenGL)
|
||||
{
|
||||
Con::errorf("The requested renderer, %s, doesn't seem to be available."
|
||||
" Trying the default, OpenGL.", getAdapterNameFromType(type));
|
||||
adapter = GFXInit::getAdapterOfType(OpenGL);
|
||||
adapter = GFXInit::getAdapterOfType(OpenGL, outputDevice);
|
||||
}
|
||||
|
||||
if(!adapter)
|
||||
{
|
||||
Con::errorf("The OpenGL renderer doesn't seem to be available. Trying the GFXNulDevice.");
|
||||
adapter = GFXInit::getAdapterOfType(NullDevice);
|
||||
adapter = GFXInit::getAdapterOfType(NullDevice, "");
|
||||
}
|
||||
|
||||
AssertFatal( adapter, "There is no rendering device available whatsoever.");
|
||||
|
|
@ -226,8 +254,9 @@ GFXAdapter *GFXInit::getBestAdapterChoice()
|
|||
{
|
||||
// Get the user's preference for device...
|
||||
const String renderer = Con::getVariable("$pref::Video::displayDevice");
|
||||
GFXAdapterType adapterType = getAdapterTypeFromName(renderer);
|
||||
GFXAdapter *adapter = chooseAdapter(adapterType);
|
||||
const String outputDevice = Con::getVariable("$pref::Video::displayOutputDevice");
|
||||
GFXAdapterType adapterType = getAdapterTypeFromName(renderer.c_str());
|
||||
GFXAdapter *adapter = chooseAdapter(adapterType, outputDevice.c_str());
|
||||
|
||||
// Did they have one? Return it.
|
||||
if(adapter)
|
||||
|
|
@ -341,7 +370,7 @@ void GFXInit::enumerateAdapters()
|
|||
|
||||
GFXDevice *GFXInit::createDevice( GFXAdapter *adapter )
|
||||
{
|
||||
Con::printf("Attempting to create GFX device: %s", adapter->getName());
|
||||
Con::printf("Attempting to create GFX device: %s [%s]", adapter->getName(), adapter->getOutputName());
|
||||
|
||||
GFXDevice* temp = adapter->mCreateDeviceInstanceDelegate(adapter->mIndex);
|
||||
if (temp)
|
||||
|
|
@ -387,6 +416,20 @@ DefineEngineStaticMethod( GFXInit, getAdapterName, String, ( S32 index ),,
|
|||
return String::EmptyString;
|
||||
}
|
||||
|
||||
DefineEngineStaticMethod( GFXInit, getAdapterOutputName, String, ( S32 index ),,
|
||||
"Returns the name of the graphics adapter's output display device.\n"
|
||||
"@param index The index of the adapter." )
|
||||
{
|
||||
Vector<GFXAdapter*> adapters( __FILE__, __LINE__ );
|
||||
GFXInit::getAdapters(&adapters);
|
||||
|
||||
if(index >= 0 && index < adapters.size())
|
||||
return adapters[index]->mOutputName;
|
||||
|
||||
Con::errorf( "GFXInit::getAdapterOutputName - Out of range adapter index." );
|
||||
return String::EmptyString;
|
||||
}
|
||||
|
||||
DefineEngineStaticMethod( GFXInit, getAdapterType, GFXAdapterType, ( S32 index ),,
|
||||
"Returns the type (D3D9, D3D8, GL, Null) of a graphics adapter.\n"
|
||||
"@param index The index of the adapter." )
|
||||
|
|
@ -486,7 +529,7 @@ DefineEngineStaticMethod( GFXInit, createNullDevice, void, (),,
|
|||
GFXInit::enumerateAdapters();
|
||||
|
||||
// Create a device.
|
||||
GFXAdapter *a = GFXInit::chooseAdapter(NullDevice);
|
||||
GFXAdapter *a = GFXInit::chooseAdapter(NullDevice, "");
|
||||
|
||||
GFXDevice *newDevice = GFX;
|
||||
|
||||
|
|
|
|||
|
|
@ -65,15 +65,19 @@ public:
|
|||
/// Get the number of available adapters.
|
||||
static S32 getAdapterCount();
|
||||
|
||||
/// Compares the adapter's output display device with the given output display device
|
||||
static bool compareAdapterOutputDevice(const GFXAdapter* adapter, const char* outputDevice);
|
||||
|
||||
/// Chooses a suitable GFXAdapter, based on type, preferences, and fallbacks.
|
||||
/// If the requested type is omitted, we use the prefs value.
|
||||
/// If the requested type isn't found, we use fallbacks: OpenGL, NullDevice
|
||||
/// This method never returns NULL.
|
||||
static GFXAdapter *chooseAdapter( GFXAdapterType type);
|
||||
static GFXAdapter *chooseAdapter( GFXAdapterType type, const char* outputDevice);
|
||||
|
||||
/// Gets the first adapter of the requested type from the list of enumerated
|
||||
/// adapters. Should only call this after a call to enumerateAdapters.
|
||||
static GFXAdapter *getAdapterOfType( GFXAdapterType type );
|
||||
/// Gets the first adapter of the requested type (and on the requested output device)
|
||||
/// from the list of enumerated adapters. Should only call this after a call to
|
||||
/// enumerateAdapters.
|
||||
static GFXAdapter *getAdapterOfType( GFXAdapterType type, const char* outputDevice );
|
||||
|
||||
/// Converts a GFXAdapterType to a string name. Useful for writing out prefs
|
||||
static const char *getAdapterNameFromType( GFXAdapterType type );
|
||||
|
|
|
|||
|
|
@ -2314,6 +2314,40 @@ DefineEngineMethod( GuiCanvas, setWindowTitle, void, ( const char* newTitle),,
|
|||
}
|
||||
|
||||
|
||||
DefineEngineMethod( GuiCanvas, findFirstMatchingMonitor, S32, (const char* name),,
|
||||
"@brief Find the first monitor index that matches the given name.\n\n"
|
||||
"The actual match algorithm depends on the implementation.\n"
|
||||
"@param name The name to search for.\n\n"
|
||||
"@return The number of monitors attached to the system, including the default monoitor.")
|
||||
{
|
||||
return PlatformWindowManager::get()->findFirstMatchingMonitor(name);
|
||||
}
|
||||
|
||||
DefineEngineMethod( GuiCanvas, getMonitorCount, S32, (),,
|
||||
"@brief Gets the number of monitors attached to the system.\n\n"
|
||||
|
||||
"@return The number of monitors attached to the system, including the default monoitor.")
|
||||
{
|
||||
return PlatformWindowManager::get()->getMonitorCount();
|
||||
}
|
||||
|
||||
DefineEngineMethod( GuiCanvas, getMonitorName, const char*, (S32 index),,
|
||||
"@brief Gets the name of the requested monitor.\n\n"
|
||||
"@param index The monitor index.\n\n"
|
||||
"@return The name of the requested monitor.")
|
||||
{
|
||||
return PlatformWindowManager::get()->getMonitorName(index);
|
||||
}
|
||||
|
||||
DefineEngineMethod( GuiCanvas, getMonitorRect, RectI, (S32 index),,
|
||||
"@brief Gets the region of the requested monitor.\n\n"
|
||||
"@param index The monitor index.\n\n"
|
||||
"@return The rectangular region of the requested monitor.")
|
||||
{
|
||||
return PlatformWindowManager::get()->getMonitorRect(index);
|
||||
}
|
||||
|
||||
|
||||
DefineEngineMethod( GuiCanvas, getVideoMode, const char*, (),,
|
||||
"@brief Gets the current screen mode as a string.\n\n"
|
||||
|
||||
|
|
|
|||
|
|
@ -51,11 +51,10 @@ bool PlatformVideoInfo::profileAdapters()
|
|||
// Query the number of adapters
|
||||
String tempString;
|
||||
|
||||
mAdapters.increment( 1 );
|
||||
//if( !_queryProperty( PVI_NumAdapters, 0, &tempString ) )
|
||||
// return false;
|
||||
if( !_queryProperty( PVI_NumAdapters, 0, &tempString ) )
|
||||
return false;
|
||||
|
||||
//mAdapters.increment( dAtoi( tempString ) );
|
||||
mAdapters.increment( dAtoi( tempString ) );
|
||||
|
||||
U32 adapterNum = 0;
|
||||
for( Vector<PVIAdapter>::iterator itr = mAdapters.begin(); itr != mAdapters.end(); itr++ )
|
||||
|
|
@ -85,6 +84,8 @@ bool PlatformVideoInfo::profileAdapters()
|
|||
#undef _QUERY_MASK_HELPER
|
||||
|
||||
// Test flags here for success
|
||||
|
||||
++adapterNum;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ struct DXDIAG_INIT_PARAMS
|
|||
|
||||
struct IDxDiagContainer : public IUnknown
|
||||
{
|
||||
virtual HRESULT STDMETHODCALLTYPE GetNumberOfChildContaiiners( DWORD* pdwCount ) = 0;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetNumberOfChildContainers( DWORD* pdwCount ) = 0;
|
||||
virtual HRESULT STDMETHODCALLTYPE EnumChildContainerNames( DWORD dwIndex, LPWSTR pwszContainer, DWORD cchContainer ) = 0;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetChildContainer( LPCWSTR pwszContainer, IDxDiagContainer** ppInstance ) = 0;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetNumberOfProps( DWORD* pdwCount ) = 0;
|
||||
|
|
@ -361,6 +361,28 @@ bool WMIVideoInfo::_queryPropertyDxDiag( const PVIQueryType queryType, const U32
|
|||
IDxDiagContainer* displayDevicesContainer = 0;
|
||||
IDxDiagContainer* deviceContainer = 0;
|
||||
|
||||
// Special case to deal with PVI_NumAdapters
|
||||
if(queryType == PVI_NumAdapters)
|
||||
{
|
||||
DWORD count = 0;
|
||||
String value;
|
||||
|
||||
if( mDxDiagProvider->GetRootContainer( &rootContainer ) == S_OK
|
||||
&& rootContainer->GetChildContainer( L"DxDiag_DisplayDevices", &displayDevicesContainer ) == S_OK
|
||||
&& displayDevicesContainer->GetNumberOfChildContainers( &count ) == S_OK )
|
||||
{
|
||||
value = String::ToString("%d", count);
|
||||
}
|
||||
|
||||
if( rootContainer )
|
||||
SAFE_RELEASE( rootContainer );
|
||||
if( displayDevicesContainer )
|
||||
SAFE_RELEASE( displayDevicesContainer );
|
||||
|
||||
*outValue = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
WCHAR adapterIdString[ 2 ];
|
||||
adapterIdString[ 0 ] = L'0' + adapterId;
|
||||
adapterIdString[ 1 ] = L'\0';
|
||||
|
|
|
|||
|
|
@ -71,6 +71,25 @@ public:
|
|||
/// @return The current desktop bit depth, or Point2I(-1,-1) if an error occurred
|
||||
virtual Point2I getDesktopResolution() = 0;
|
||||
|
||||
// Build out the monitor list.
|
||||
virtual void buildMonitorsList() {}
|
||||
|
||||
// Find the first monitor index that matches the given name. The actual match
|
||||
// algorithm depends on the implementation. Provides a default value of -1 to
|
||||
// indicate no match.
|
||||
virtual S32 findFirstMatchingMonitor(const char* name) { return -1; }
|
||||
|
||||
// Retrieve the number of monitors. Provides a default count of 0 for systems that
|
||||
// don't provide information on connected monitors.
|
||||
virtual U32 getMonitorCount() { return 0; }
|
||||
|
||||
// Get the name of the requested monitor. Provides a default of "" for platorms
|
||||
// that do not provide information on connected monitors.
|
||||
virtual const char* getMonitorName(U32 index) { return ""; }
|
||||
|
||||
// Get the requested monitor's rectangular region.
|
||||
virtual RectI getMonitorRect(U32 index) { return RectI(0, 0, 0, 0); }
|
||||
|
||||
/// Populate a vector with all monitors and their extents in window space.
|
||||
virtual void getMonitorRegions(Vector<RectI> ®ions) = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -667,6 +667,9 @@ LRESULT PASCAL Win32Window::WindowProc( HWND hWnd, UINT message, WPARAM wParam,
|
|||
{
|
||||
|
||||
case WM_DISPLAYCHANGE:
|
||||
// Update the monitor list
|
||||
PlatformWindowManager::get()->buildMonitorsList();
|
||||
|
||||
if(window && window->isVisible() && !window->mSuppressReset && window->getVideoMode().bitDepth != wParam)
|
||||
{
|
||||
Con::warnf("Win32Window::WindowProc - resetting device due to display mode BPP change.");
|
||||
|
|
|
|||
|
|
@ -52,6 +52,8 @@ Win32WindowManager::Win32WindowManager()
|
|||
mCurtainWindow = NULL;
|
||||
|
||||
mOffscreenRender = false;
|
||||
|
||||
buildMonitorsList();
|
||||
}
|
||||
|
||||
Win32WindowManager::~Win32WindowManager()
|
||||
|
|
@ -106,6 +108,74 @@ S32 Win32WindowManager::getDesktopBitDepth()
|
|||
}
|
||||
|
||||
BOOL Win32WindowManager::MonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData )
|
||||
{
|
||||
Vector<MonitorInfo> * monitors = (Vector<MonitorInfo>*)dwData;
|
||||
|
||||
// Fill out the new monitor structure
|
||||
monitors->increment();
|
||||
MonitorInfo& monitor = monitors->last();
|
||||
monitor.monitorHandle = hMonitor;
|
||||
monitor.region.point.x = lprcMonitor->left;
|
||||
monitor.region.point.y = lprcMonitor->top;
|
||||
monitor.region.extent.x = lprcMonitor->right - lprcMonitor->left;
|
||||
monitor.region.extent.y = lprcMonitor->bottom - lprcMonitor->top;
|
||||
|
||||
MONITORINFOEX info;
|
||||
info.cbSize = sizeof(MONITORINFOEX);
|
||||
if(GetMonitorInfo(hMonitor, &info))
|
||||
{
|
||||
monitor.name = info.szDevice;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Win32WindowManager::buildMonitorsList()
|
||||
{
|
||||
// Clear the list
|
||||
mMonitors.clear();
|
||||
|
||||
// Enumerate all monitors
|
||||
EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, (U32)(void*)&mMonitors);
|
||||
}
|
||||
|
||||
S32 Win32WindowManager::findFirstMatchingMonitor(const char* name)
|
||||
{
|
||||
// Try and match the first part of the output device display name. For example,
|
||||
// a Monitor name of "\\.\DISPLAY1" might correspond to a display name
|
||||
// of "\\.\DISPLAY1\Monitor0". If two monitors are set up in duplicate mode then
|
||||
// they will have the same 'display' part in their display name.
|
||||
for(U32 i=0; i<mMonitors.size(); ++i)
|
||||
{
|
||||
if(dStrstr(name, mMonitors[i].name) == name)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
U32 Win32WindowManager::getMonitorCount()
|
||||
{
|
||||
return mMonitors.size();
|
||||
}
|
||||
|
||||
const char* Win32WindowManager::getMonitorName(U32 index)
|
||||
{
|
||||
if(index >= mMonitors.size())
|
||||
return "";
|
||||
|
||||
return mMonitors[index].name.c_str();
|
||||
}
|
||||
|
||||
RectI Win32WindowManager::getMonitorRect(U32 index)
|
||||
{
|
||||
if(index >= mMonitors.size())
|
||||
return RectI(0, 0, 0, 0);
|
||||
|
||||
return mMonitors[index].region;
|
||||
}
|
||||
|
||||
BOOL Win32WindowManager::MonitorRegionEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData )
|
||||
{
|
||||
Vector<RectI> * regions = (Vector<RectI>*)dwData;
|
||||
|
||||
|
|
@ -120,7 +190,7 @@ BOOL Win32WindowManager::MonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRE
|
|||
|
||||
void Win32WindowManager::getMonitorRegions(Vector<RectI> ®ions)
|
||||
{
|
||||
EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, (U32)(void*)®ions);
|
||||
EnumDisplayMonitors(NULL, NULL, MonitorRegionEnumProc, (U32)(void*)®ions);
|
||||
}
|
||||
|
||||
void Win32WindowManager::getWindows(VectorPtr<PlatformWindow*> &windows)
|
||||
|
|
|
|||
|
|
@ -56,6 +56,16 @@ class Win32WindowManager : public PlatformWindowManager
|
|||
// is intended for offscreen rendering
|
||||
bool mOffscreenRender;
|
||||
|
||||
/// Internal structure used when enumerating monitors
|
||||
struct MonitorInfo {
|
||||
HMONITOR monitorHandle;
|
||||
RectI region;
|
||||
String name;
|
||||
};
|
||||
|
||||
/// Array of enumerated monitors
|
||||
Vector<MonitorInfo> mMonitors;
|
||||
|
||||
/// Callback to receive information about available monitors.
|
||||
static BOOL CALLBACK MonitorEnumProc(
|
||||
HMONITOR hMonitor, // handle to display monitor
|
||||
|
|
@ -64,6 +74,14 @@ class Win32WindowManager : public PlatformWindowManager
|
|||
LPARAM dwData // data
|
||||
);
|
||||
|
||||
/// Callback to receive information about available monitor regions
|
||||
static BOOL CALLBACK MonitorRegionEnumProc(
|
||||
HMONITOR hMonitor, // handle to display monitor
|
||||
HDC hdcMonitor, // handle to monitor DC
|
||||
LPRECT lprcMonitor, // monitor intersection rectangle
|
||||
LPARAM dwData // data
|
||||
);
|
||||
|
||||
/// If a curtain window is present, then its HWND will be stored here.
|
||||
HWND mCurtainWindow;
|
||||
|
||||
|
|
@ -75,6 +93,15 @@ public:
|
|||
virtual S32 getDesktopBitDepth();
|
||||
virtual Point2I getDesktopResolution();
|
||||
|
||||
/// Build out the monitors list. Also used to rebuild the list after
|
||||
/// a WM_DISPLAYCHANGE message.
|
||||
virtual void buildMonitorsList();
|
||||
|
||||
virtual S32 findFirstMatchingMonitor(const char* name);
|
||||
virtual U32 getMonitorCount();
|
||||
virtual const char* getMonitorName(U32 index);
|
||||
virtual RectI getMonitorRect(U32 index);
|
||||
|
||||
virtual void getMonitorRegions(Vector<RectI> ®ions);
|
||||
virtual PlatformWindow *createWindow(GFXDevice *device, const GFXVideoMode &mode);
|
||||
virtual void getWindows(VectorPtr<PlatformWindow*> &windows);
|
||||
|
|
|
|||
Loading…
Reference in a new issue