123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569 |
- //-----------------------------------------------------------------------------
- // Copyright (c) 2012 GarageGames, LLC
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to
- // deal in the Software without restriction, including without limitation the
- // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- // sell copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- // IN THE SOFTWARE.
- //-----------------------------------------------------------------------------
- #include "platform/platform.h"
- #include "gfx/gfxInit.h"
- #include "gfx/gfxTextureManager.h"
- #include "gfx/gfxAPI.h"
- #include "console/console.h"
- #include "windowManager/platformWindowMgr.h"
- #include "core/module.h"
- Vector<GFXAdapter*> GFXInit::smAdapters( __FILE__, __LINE__ );
- GFXInit::RegisterDeviceSignal* GFXInit::smRegisterDeviceSignal;
- MODULE_BEGIN( GFX )
- MODULE_INIT
- {
- GFXInit::init();
- if( engineAPI::gUseConsoleInterop )
- GFXDevice::initConsole();
- GFXTextureManager::init();
- }
-
- MODULE_SHUTDOWN
- {
- GFXDevice::destroy();
- GFXInit::cleanup();
- }
- MODULE_END;
- IMPLEMENT_STATIC_CLASS( GFXInit, GFXAPI,
- "Functions for tracking GFX adapters and initializing them into devices."
- );
- ConsoleDoc(
- "@class GFXInit\n"
- "@ingroup GFX\n"
- "@brief Functions for tracking GFX adapters and initializing them into devices.\n"
- );
- inline static void _GFXInitReportAdapters(Vector<GFXAdapter*> &adapters)
- {
- for (U32 i = 0; i < adapters.size(); i++)
- {
- switch (adapters[i]->mType)
- {
- case OpenGL:
- Con::printf(" OpenGL device found");
- break;
- case NullDevice:
- Con::printf(" Null device found");
- break;
- case Direct3D11:
- Con::printf(" Direct 3D (version 11.x) device found");
- break;
- default :
- Con::printf(" Unknown device found");
- break;
- }
- }
- }
- inline static void _GFXInitGetInitialRes(GFXVideoMode &vm)
- {
- // cache the desktop size of the main screen
- GFXVideoMode desktopVm = GFXInit::getDesktopResolution();
- // load pref variables, properly choose windowed / fullscreen
- const String resString = Con::getVariable("$pref::Video::mode");
- // Parse video mode settings from pref string
- vm.parseFromString(resString);
- }
- GFXInit::RegisterDeviceSignal& GFXInit::getRegisterDeviceSignal()
- {
- if (smRegisterDeviceSignal)
- return *smRegisterDeviceSignal;
- smRegisterDeviceSignal = new RegisterDeviceSignal();
- return *smRegisterDeviceSignal;
- }
- void GFXInit::init()
- {
- // init only once.
- static bool doneOnce = false;
- if(doneOnce)
- return;
- doneOnce = true;
-
- Con::printf( "GFX Init:" );
- //find our adapters
- Vector<GFXAdapter*> adapters( __FILE__, __LINE__ );
- GFXInit::enumerateAdapters();
- GFXInit::getAdapters(&adapters);
- if(!adapters.size())
- Con::errorf("Could not find a display adapter");
- //loop through and tell the user what kind of adapters we found
- _GFXInitReportAdapters(adapters);
- Con::printf( "" );
- }
- void GFXInit::cleanup()
- {
- while( smAdapters.size() )
- {
- GFXAdapter* adapter = smAdapters.last();
- smAdapters.decrement();
- delete adapter;
- }
- if( smRegisterDeviceSignal )
- SAFE_DELETE( smRegisterDeviceSignal );
- }
- bool GFXInit::compareAdapterOutputDevice(const GFXAdapter* adapter, const char* outputDevice)
- {
- // 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 )
- {
- 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 NULL;
- }
- GFXAdapter* GFXInit::getAdapterOfType(GFXAdapterType type, S32 outputDeviceIndex)
- {
- for (U32 i = 0; i < smAdapters.size(); i++)
- {
- if (smAdapters[i]->mType == type)
- {
- if (smAdapters[i]->mIndex == outputDeviceIndex)
- {
- return smAdapters[i];
- }
- }
- }
- return NULL;
- }
- GFXAdapter* GFXInit::chooseAdapter( GFXAdapterType type, const char* outputDevice)
- {
- 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, outputDevice);
- }
-
- if(!adapter)
- {
- Con::errorf("The OpenGL renderer doesn't seem to be available. Trying the GFXNulDevice.");
- adapter = GFXInit::getAdapterOfType(NullDevice, "");
- }
-
- AssertFatal( adapter, "There is no rendering device available whatsoever.");
- return adapter;
- }
- GFXAdapter* GFXInit::chooseAdapter(GFXAdapterType type, S32 outputDeviceIndex)
- {
- GFXAdapter* adapter = GFXInit::getAdapterOfType(type, outputDeviceIndex);
- 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, outputDeviceIndex);
- }
- if (!adapter)
- {
- Con::errorf("The OpenGL renderer doesn't seem to be available. Trying the GFXNulDevice.");
- adapter = GFXInit::getAdapterOfType(NullDevice, 0);
- }
- AssertFatal(adapter, "There is no rendering device available whatsoever.");
- return adapter;
- }
- const char* GFXInit::getAdapterNameFromType(GFXAdapterType type)
- {
- // must match GFXAdapterType order
- static const char* _names[] = { "OpenGL", "D3D11", "NullDevice" };
-
- if( type < 0 || type >= GFXAdapterType_Count )
- {
- Con::errorf( "GFXInit::getAdapterNameFromType - Invalid renderer type, defaulting to OpenGL" );
- return _names[OpenGL];
- }
-
- return _names[type];
- }
- GFXAdapterType GFXInit::getAdapterTypeFromName(const char* name)
- {
- S32 ret = -1;
- for(S32 i = 0; i < GFXAdapterType_Count; i++)
- {
- if( !dStricmp( getAdapterNameFromType((GFXAdapterType)i), name ) )
- ret = i;
- }
-
- if( ret == -1 )
- {
- Con::errorf( "GFXInit::getAdapterTypeFromName - Invalid renderer name, defaulting to D3D11" );
- ret = Direct3D11;
- }
-
- return (GFXAdapterType)ret;
- }
- GFXAdapter *GFXInit::getBestAdapterChoice()
- {
- // Get the user's preference for device...
- const String renderer = Con::getVariable("$pref::Video::displayDevice");
- const String outputDevice = Con::getVariable("$pref::Video::displayOutputDevice");
- const String adapterDevice = Con::getVariable("$Video::forceDisplayAdapter");
- GFXAdapterType adapterType = getAdapterTypeFromName(renderer.c_str());;
- GFXAdapter *adapter = NULL;
- if (adapterDevice.isEmpty())
- {
- adapter = chooseAdapter(adapterType, outputDevice.c_str());
- }
- else
- {
- S32 adapterIdx = dAtoi(adapterDevice.c_str());
- if (adapterIdx == -1)
- adapter = chooseAdapter(NullDevice, outputDevice.c_str());
- else
- adapter = chooseAdapter(adapterType, adapterIdx);
- }
- // Did they have one? Return it.
- if(adapter)
- return adapter;
- // Didn't have one. So make it up. Find the highest SM available. Prefer
- // D3D to GL because if we have a D3D device at all we're on windows,
- // and in an unknown situation on Windows D3D is probably the safest bet.
- //
- // If D3D is unavailable, we're not on windows, so GL is de facto the
- // best choice!
- F32 highestSMDX = 0.f, highestSMGL = 0.f;
- GFXAdapter *foundAdapterGL = NULL, *foundAdapter11 = NULL;
- for (S32 i = 0; i<smAdapters.size(); i++)
- {
- GFXAdapter *currAdapter = smAdapters[i];
- switch (currAdapter->mType)
- {
- case Direct3D11:
- if (currAdapter->mShaderModel > highestSMDX)
- {
- highestSMDX = currAdapter->mShaderModel;
- foundAdapter11 = currAdapter;
- }
- break;
- case OpenGL:
- if (currAdapter->mShaderModel > highestSMGL)
- {
- highestSMGL = currAdapter->mShaderModel;
- foundAdapterGL = currAdapter;
- }
- break;
- default:
- break;
- }
- }
- // Return best found in order DX11, GL
- if (foundAdapter11)
- return foundAdapter11;
- if (foundAdapterGL)
- return foundAdapterGL;
- // Uh oh - we didn't find anything. Grab whatever we can that's not Null...
- for(S32 i=0; i<smAdapters.size(); i++)
- if(smAdapters[i]->mType != NullDevice)
- return smAdapters[i];
- // Dare we return a null device? No. Just return NULL.
- return NULL;
- }
- GFXVideoMode GFXInit::getInitialVideoMode()
- {
- GFXVideoMode vm;
- _GFXInitGetInitialRes(vm);
- return vm;
- }
- S32 GFXInit::getAdapterCount()
- {
- return smAdapters.size();
- }
- void GFXInit::getAdapters(Vector<GFXAdapter*> *adapters)
- {
- adapters->clear();
- for (U32 k = 0; k < smAdapters.size(); k++)
- adapters->push_back(smAdapters[k]);
- }
- GFXVideoMode GFXInit::getDesktopResolution()
- {
- GFXVideoMode resVm;
- // Retrieve Resolution Information.
- resVm.bitDepth = WindowManager->getDesktopBitDepth();
- resVm.resolution = WindowManager->getDesktopResolution();
- resVm.fullScreen = false;
- resVm.refreshRate = 60;
- // Return results
- return resVm;
- }
- void GFXInit::enumerateAdapters()
- {
- // Call each device class and have it report any adapters it supports.
- if(smAdapters.size())
- {
- // CodeReview Seems like this is ok to just ignore? [bjg, 5/19/07]
- //Con::warnf("GFXInit::enumerateAdapters - already have a populated adapter list, aborting re-analysis.");
- return;
- }
- getRegisterDeviceSignal().trigger(GFXInit::smAdapters);
- }
- GFXDevice *GFXInit::createDevice( GFXAdapter *adapter )
- {
- Con::printf("Attempting to create GFX device: %s [%s]", adapter->getName(), adapter->getOutputName());
- GFXDevice* temp = adapter->mCreateDeviceInstanceDelegate(adapter->mIndex);
- if (temp)
- {
- Con::printf("Device created, setting adapter and enumerating modes");
- temp->setAdapter(*adapter);
- temp->enumerateVideoModes();
- temp->getVideoModeList();
- }
- else
- Con::errorf("Failed to create GFX device");
- GFXDevice::getDeviceEventSignal().trigger(GFXDevice::deCreate);
- return temp;
- }
- DefineEngineFunction( getDesktopResolution, Point3F, (),,
- "Returns the width, height, and bitdepth of the screen/desktop.\n\n@ingroup GFX" )
- {
- GFXVideoMode res = GFXInit::getDesktopResolution();
- return Point3F( res.resolution.x, res.resolution.y, res.bitDepth );
- }
- DefineEngineStaticMethod( GFXInit, getAdapterCount, S32, (),,
- "Return the number of graphics adapters available. @ingroup GFX")
- {
- return GFXInit::getAdapterCount();
- }
- DefineEngineStaticMethod( GFXInit, getAdapterName, String, ( S32 index ),,
- "Returns the name of the graphics adapter.\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]->mName;
- Con::errorf( "GFXInit::getAdapterName - Out of range adapter 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 (D3D11, GL, Null) of a graphics adapter.\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]->mType;
- Con::errorf( "GFXInit::getAdapterType - Out of range adapter index." );
- return GFXAdapterType_Count;
- }
- DefineEngineStaticMethod( GFXInit, getAdapterShaderModel, F32, ( S32 index ),,
- "Returns the supported shader model of the graphics adapter or -1 if the index is bad.\n"
- "@param index The index of the adapter." )
- {
- Vector<GFXAdapter*> adapters( __FILE__, __LINE__ );
- GFXInit::getAdapters(&adapters);
- if(index < 0 || index >= adapters.size())
- {
- Con::errorf("GFXInit::getAdapterShaderModel - Out of range adapter index.");
- return -1.0f;
- }
- return adapters[index]->mShaderModel;
- }
- DefineEngineStaticMethod( GFXInit, getDefaultAdapterIndex, S32, (),,
- "Returns the index of the default graphics adapter. This is the graphics device "
- "which will be used to initialize the engine." )
- {
- GFXAdapter *a = GFXInit::getBestAdapterChoice();
- // We have to find the index of the adapter in the list to
- // return an index that makes sense to the script.
- Vector<GFXAdapter*> adapters( __FILE__, __LINE__ );
- GFXInit::getAdapters(&adapters);
- for(S32 i=0; i<adapters.size(); i++)
- if ( adapters[i]->mIndex == a->mIndex &&
- adapters[i]->mType == a->mType )
- return i;
- Con::warnf( "GFXInit::getDefaultAdapterIndex - Didn't find the adapter in the list!" );
- return -1;
- }
- DefineEngineStaticMethod( GFXInit, getAdapterModeCount, S32, ( S32 index ),,
- "Gets the number of modes available on the specified adapter.\n\n"
- "@param index Index of the adapter to get modes from.\n"
- "@return The number of video modes supported by the adapter or -1 if the given adapter was not found." )
- {
- Vector<GFXAdapter*> adapters( __FILE__, __LINE__ );
- GFXInit::getAdapters(&adapters);
- if( index < 0 || index >= adapters.size())
- {
- Con::warnf( "GFXInit::getAdapterModeCount - The index was out of range." );
- return -1;
- }
- return adapters[index]->mAvailableModes.size();
- }
- DefineEngineStaticMethod( GFXInit, getAdapterMode, String, ( S32 index, S32 modeIndex ),,
- "Gets the details of the specified adapter mode.\n\n"
- "@param index Index of the adapter to query.\n"
- "@param modeIndex Index of the mode to get data from.\n"
- "@return A video mode string in the format 'width height fullscreen bitDepth refreshRate aaLevel'.\n"
- "@see GuiCanvas::getVideoMode()" )
- {
- Vector<GFXAdapter*> adapters( __FILE__, __LINE__ );
- GFXInit::getAdapters(&adapters);
- if ( index < 0 || index >= adapters.size() )
- {
- Con::warnf( "GFXInit::getAdapterMode - The adapter index was out of range." );
- return String::EmptyString;
- }
- if ( modeIndex < 0 || modeIndex >= adapters[index]->mAvailableModes.size() )
- {
- Con::warnf( "GFXInit::getAdapterMode - The mode index was out of range." );
- return String::EmptyString;
- }
- const GFXVideoMode &vm = adapters[index]->mAvailableModes[modeIndex];
- return vm.toString();
- }
- DefineEngineStaticMethod( GFXInit, createNullDevice, void, (),,
- "Create the NULL graphics device used for testing or headless operation." )
- {
- // Enumerate things for GFX before we have an active device.
- GFXInit::enumerateAdapters();
-
- // Create a device.
- GFXAdapter *a = GFXInit::chooseAdapter(NullDevice, "");
-
- GFXDevice *newDevice = GFX;
-
- // Do we have a global device already? (This is the site if you want
- // to start rendering to multiple devices simultaneously)
- if(newDevice == NULL)
- newDevice = GFXInit::createDevice(a);
-
- newDevice->setAllowRender( false );
- }
|