gfxInit.cpp

Engine/source/gfx/gfxInit.cpp

More...

Public Functions

ConsoleDoc("@class <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">GFXInit\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">GFX\n</a>" "@brief Functions <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> tracking <a href="/coding/file/gfxdevice_8h/#gfxdevice_8h_1afd23debb5edac4f53e564f02e6964c62">GFX</a> adapters and initializing them into <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">devices.\n</a>" )
DefineEngineFunction(getDesktopResolution , Point3F , () , "Returns the width, height , and bitdepth of the screen/<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">desktop.\n\n</a> @ingroup <a href="/coding/file/gfxdevice_8h/#gfxdevice_8h_1afd23debb5edac4f53e564f02e6964c62">GFX</a>" )
DefineEngineStaticMethod(GFXInit , createNullDevice , void , () , "Create the <a href="/coding/file/typesx86unix_8h/#typesx86unix_8h_1a070d2ce7b6bb7e5c05602aa8c308d0c4">NULL</a> graphics device used <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> testing or headless operation." )
DefineEngineStaticMethod(GFXInit , getAdapterCount , S32 , () , "Return the number of graphics adapters available. @ingroup <a href="/coding/file/gfxdevice_8h/#gfxdevice_8h_1afd23debb5edac4f53e564f02e6964c62">GFX</a>" )
DefineEngineStaticMethod(GFXInit , getAdapterMode , String , (S32 index, S32 modeIndex) , "Gets the details of the specified adapter <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">mode.\n\n</a>" "@param index Index of the adapter <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">query.\n</a>" "@param modeIndex Index of the <a href="/coding/file/zipobject_8cpp/#zipobject_8cpp_1ac6c3dfb4c3a68f849f32cbfb21da4e77">mode</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> get data <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">from.\n</a>" "@return A video <a href="/coding/file/zipobject_8cpp/#zipobject_8cpp_1ac6c3dfb4c3a68f849f32cbfb21da4e77">mode</a> string in the format 'width height fullscreen bitDepth refreshRate aaLevel'.\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@see GuiCanvas::getVideoMode()" )
DefineEngineStaticMethod(GFXInit , getAdapterModeCount , S32 , (S32 index) , "Gets the number of modes available on the specified <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">adapter.\n\n</a>" "@param index Index of the adapter <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> get modes <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">from.\n</a>" "@return The number of video modes supported by the adapter or -1 <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the given adapter was not found." )
DefineEngineStaticMethod(GFXInit , getAdapterName , String , (S32 index) , "Returns the name of the graphics <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">adapter.\n</a>" "@param index The index of the adapter." )
DefineEngineStaticMethod(GFXInit , getAdapterOutputName , String , (S32 index) , "Returns the name of the graphics adapter's output display <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">device.\n</a>" "@param index The index of the adapter." )
DefineEngineStaticMethod(GFXInit , getAdapterShaderModel , F32 , (S32 index) , "Returns the supported shader model of the graphics adapter or -1 <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the index is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">bad.\n</a>" "@param index The index of the adapter." )
DefineEngineStaticMethod(GFXInit , getAdapterType , GFXAdapterType , (S32 index) , "Returns the type (<a href="/coding/file/gfxd3d11device_8h/#gfxd3d11device_8h_1a60ee39488fe07edb777dba8df63fdc23">D3D11</a>, GL, Null) of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> graphics <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">adapter.\n</a>" "@param index The index of the adapter." )
DefineEngineStaticMethod(GFXInit , getDefaultAdapterIndex , S32 , () , "Returns the index of the default graphics adapter. This is the graphics device " "which will be used <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> initialize the engine." )
IMPLEMENT_STATIC_CLASS(GFXInit , GFXAPI , "Functions <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> tracking <a href="/coding/file/gfxdevice_8h/#gfxdevice_8h_1afd23debb5edac4f53e564f02e6964c62">GFX</a> adapters and initializing them into devices." )

Detailed Description

Public Variables

 MODULE_END 
 MODULE_INIT 
 MODULE_SHUTDOWN 

Public Functions

_GFXInitGetInitialRes(GFXVideoMode & vm)

_GFXInitReportAdapters(Vector< GFXAdapter * > & adapters)

ConsoleDoc("@class <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">GFXInit\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">GFX\n</a>" "@brief Functions <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> tracking <a href="/coding/file/gfxdevice_8h/#gfxdevice_8h_1afd23debb5edac4f53e564f02e6964c62">GFX</a> adapters and initializing them into <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">devices.\n</a>" )

DefineEngineFunction(getDesktopResolution , Point3F , () , "Returns the width, height , and bitdepth of the screen/<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">desktop.\n\n</a> @ingroup <a href="/coding/file/gfxdevice_8h/#gfxdevice_8h_1afd23debb5edac4f53e564f02e6964c62">GFX</a>" )

DefineEngineStaticMethod(GFXInit , createNullDevice , void , () , "Create the <a href="/coding/file/typesx86unix_8h/#typesx86unix_8h_1a070d2ce7b6bb7e5c05602aa8c308d0c4">NULL</a> graphics device used <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> testing or headless operation." )

DefineEngineStaticMethod(GFXInit , getAdapterCount , S32 , () , "Return the number of graphics adapters available. @ingroup <a href="/coding/file/gfxdevice_8h/#gfxdevice_8h_1afd23debb5edac4f53e564f02e6964c62">GFX</a>" )

DefineEngineStaticMethod(GFXInit , getAdapterMode , String , (S32 index, S32 modeIndex) , "Gets the details of the specified adapter <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">mode.\n\n</a>" "@param index Index of the adapter <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">query.\n</a>" "@param modeIndex Index of the <a href="/coding/file/zipobject_8cpp/#zipobject_8cpp_1ac6c3dfb4c3a68f849f32cbfb21da4e77">mode</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> get data <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">from.\n</a>" "@return A video <a href="/coding/file/zipobject_8cpp/#zipobject_8cpp_1ac6c3dfb4c3a68f849f32cbfb21da4e77">mode</a> string in the format 'width height fullscreen bitDepth refreshRate aaLevel'.\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@see GuiCanvas::getVideoMode()" )

DefineEngineStaticMethod(GFXInit , getAdapterModeCount , S32 , (S32 index) , "Gets the number of modes available on the specified <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">adapter.\n\n</a>" "@param index Index of the adapter <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> get modes <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">from.\n</a>" "@return The number of video modes supported by the adapter or -1 <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the given adapter was not found." )

DefineEngineStaticMethod(GFXInit , getAdapterName , String , (S32 index) , "Returns the name of the graphics <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">adapter.\n</a>" "@param index The index of the adapter." )

DefineEngineStaticMethod(GFXInit , getAdapterOutputName , String , (S32 index) , "Returns the name of the graphics adapter's output display <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">device.\n</a>" "@param index The index of the adapter." )

DefineEngineStaticMethod(GFXInit , getAdapterShaderModel , F32 , (S32 index) , "Returns the supported shader model of the graphics adapter or -1 <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the index is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">bad.\n</a>" "@param index The index of the adapter." )

DefineEngineStaticMethod(GFXInit , getAdapterType , GFXAdapterType , (S32 index) , "Returns the type (<a href="/coding/file/gfxd3d11device_8h/#gfxd3d11device_8h_1a60ee39488fe07edb777dba8df63fdc23">D3D11</a>, GL, Null) of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> graphics <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">adapter.\n</a>" "@param index The index of the adapter." )

DefineEngineStaticMethod(GFXInit , getDefaultAdapterIndex , S32 , () , "Returns the index of the default graphics adapter. This is the graphics device " "which will be used <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> initialize the engine." )

IMPLEMENT_STATIC_CLASS(GFXInit , GFXAPI , "Functions <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> tracking <a href="/coding/file/gfxdevice_8h/#gfxdevice_8h_1afd23debb5edac4f53e564f02e6964c62">GFX</a> adapters and initializing them into devices." )

  1
  2//-----------------------------------------------------------------------------
  3// Copyright (c) 2012 GarageGames, LLC
  4//
  5// Permission is hereby granted, free of charge, to any person obtaining a copy
  6// of this software and associated documentation files (the "Software"), to
  7// deal in the Software without restriction, including without limitation the
  8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9// sell copies of the Software, and to permit persons to whom the Software is
 10// furnished to do so, subject to the following conditions:
 11//
 12// The above copyright notice and this permission notice shall be included in
 13// all copies or substantial portions of the Software.
 14//
 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21// IN THE SOFTWARE.
 22//-----------------------------------------------------------------------------
 23
 24#include "platform/platform.h"
 25#include "gfx/gfxInit.h"
 26
 27#include "gfx/gfxTextureManager.h"
 28#include "gfx/gfxAPI.h"
 29#include "console/console.h"
 30#include "windowManager/platformWindowMgr.h"
 31#include "core/module.h"
 32
 33
 34Vector<GFXAdapter*> GFXInit::smAdapters( __FILE__, __LINE__ );
 35GFXInit::RegisterDeviceSignal* GFXInit::smRegisterDeviceSignal;
 36
 37
 38MODULE_BEGIN( GFX )
 39
 40   MODULE_INIT
 41   {
 42      GFXInit::init();
 43      if( engineAPI::gUseConsoleInterop )
 44         GFXDevice::initConsole();
 45      GFXTextureManager::init();
 46   }
 47   
 48   MODULE_SHUTDOWN
 49   {
 50      GFXDevice::destroy();
 51      GFXInit::cleanup();
 52   }
 53
 54MODULE_END;
 55
 56IMPLEMENT_STATIC_CLASS( GFXInit, GFXAPI,
 57   "Functions for tracking GFX adapters and initializing them into devices."
 58);
 59
 60ConsoleDoc(
 61   "@class GFXInit\n"
 62   "@ingroup GFX\n"
 63   "@brief Functions for tracking GFX adapters and initializing them into devices.\n"
 64);
 65
 66inline static void _GFXInitReportAdapters(Vector<GFXAdapter*> &adapters)
 67{
 68   for (U32 i = 0; i < adapters.size(); i++)
 69   {
 70      switch (adapters[i]->mType)
 71      {
 72      case OpenGL:
 73         Con::printf("   OpenGL device found");
 74         break;
 75      case NullDevice:
 76         Con::printf("   Null device found");
 77         break;
 78      case Direct3D11:
 79         Con::printf("   Direct 3D (version 11.x) device found");
 80         break;
 81      default :
 82         Con::printf("   Unknown device found");
 83         break;
 84      }
 85   }
 86}
 87
 88inline static void _GFXInitGetInitialRes(GFXVideoMode &vm)
 89{
 90   // cache the desktop size of the main screen
 91   GFXVideoMode desktopVm = GFXInit::getDesktopResolution();
 92
 93   // load pref variables, properly choose windowed / fullscreen  
 94   const String resString = Con::getVariable("$pref::Video::mode");
 95
 96   // Parse video mode settings from pref string
 97   vm.parseFromString(resString);
 98}
 99
100GFXInit::RegisterDeviceSignal& GFXInit::getRegisterDeviceSignal()
101{
102   if (smRegisterDeviceSignal)
103      return *smRegisterDeviceSignal;
104   smRegisterDeviceSignal = new RegisterDeviceSignal();
105   return *smRegisterDeviceSignal;
106}
107
108void GFXInit::init()
109{
110   // init only once.
111   static bool doneOnce = false;
112   if(doneOnce)
113      return;
114   doneOnce = true;
115   
116   Con::printf( "GFX Init:" );
117
118   //find our adapters
119   Vector<GFXAdapter*> adapters( __FILE__, __LINE__ );
120   GFXInit::enumerateAdapters();
121   GFXInit::getAdapters(&adapters);
122
123   if(!adapters.size())
124       Con::errorf("Could not find a display adapter");
125
126   //loop through and tell the user what kind of adapters we found
127   _GFXInitReportAdapters(adapters);
128   Con::printf( "" );
129}
130
131void GFXInit::cleanup()
132{
133   while( smAdapters.size() )
134   {
135      GFXAdapter* adapter = smAdapters.last();
136      smAdapters.decrement();
137      delete adapter;
138   }
139
140   if( smRegisterDeviceSignal )
141      SAFE_DELETE( smRegisterDeviceSignal );
142}
143
144bool GFXInit::compareAdapterOutputDevice(const GFXAdapter* adapter, const char* outputDevice)
145{
146   // If the adapter doesn't have an output display device, then it supports all of them
147   if(!adapter->mOutputName[0])
148      return true;
149
150   // Try and match the first part of the output device display name.  For example,
151   // an adapter->mOutputName of "\\.\DISPLAY1" might correspond to a display name
152   // of "\\.\DISPLAY1\Monitor0".  If two monitors are set up in duplicate mode then
153   // they will have the same 'display' part in their display name.
154   return (dStrstr(outputDevice, adapter->mOutputName) == outputDevice);
155}
156
157GFXAdapter* GFXInit::getAdapterOfType( GFXAdapterType type, const char* outputDevice )
158{
159   bool testOutputDevice = false;
160   if(outputDevice && outputDevice[0])
161      testOutputDevice = true;
162
163   for( U32 i = 0; i < smAdapters.size(); i++ )
164   {
165      if( smAdapters[i]->mType == type )
166      {
167         if(testOutputDevice)
168         {
169            // Check if the output display device also matches
170            if(compareAdapterOutputDevice(smAdapters[i], outputDevice))
171            {
172               return smAdapters[i];
173            }
174         }
175         else
176         {
177            // No need to also test the output display device, so return
178            return smAdapters[i];
179         }
180      }
181   }
182
183   return NULL;
184}
185
186GFXAdapter* GFXInit::getAdapterOfType(GFXAdapterType type, S32 outputDeviceIndex)
187{
188   for (U32 i = 0; i < smAdapters.size(); i++)
189   {
190      if (smAdapters[i]->mType == type)
191      {
192         if (smAdapters[i]->mIndex == outputDeviceIndex)
193         {
194            return smAdapters[i];
195         }
196      }
197   }
198
199   return NULL;
200}
201
202GFXAdapter* GFXInit::chooseAdapter( GFXAdapterType type, const char* outputDevice)
203{
204   GFXAdapter* adapter = GFXInit::getAdapterOfType(type, outputDevice);
205   
206   if(!adapter && type != OpenGL)
207   {
208      Con::errorf("The requested renderer, %s, doesn't seem to be available."
209                  " Trying the default, OpenGL.", getAdapterNameFromType(type));
210      adapter = GFXInit::getAdapterOfType(OpenGL, outputDevice);
211   }
212   
213   if(!adapter)
214   {
215      Con::errorf("The OpenGL renderer doesn't seem to be available. Trying the GFXNulDevice.");
216      adapter = GFXInit::getAdapterOfType(NullDevice, "");
217   }
218   
219   AssertFatal( adapter, "There is no rendering device available whatsoever.");
220   return adapter;
221}
222
223GFXAdapter* GFXInit::chooseAdapter(GFXAdapterType type, S32 outputDeviceIndex)
224{
225   GFXAdapter* adapter = GFXInit::getAdapterOfType(type, outputDeviceIndex);
226
227   if (!adapter && type != OpenGL)
228   {
229      Con::errorf("The requested renderer, %s, doesn't seem to be available."
230         " Trying the default, OpenGL.", getAdapterNameFromType(type));
231      adapter = GFXInit::getAdapterOfType(OpenGL, outputDeviceIndex);
232   }
233
234   if (!adapter)
235   {
236      Con::errorf("The OpenGL renderer doesn't seem to be available. Trying the GFXNulDevice.");
237      adapter = GFXInit::getAdapterOfType(NullDevice, 0);
238   }
239
240   AssertFatal(adapter, "There is no rendering device available whatsoever.");
241   return adapter;
242}
243
244const char* GFXInit::getAdapterNameFromType(GFXAdapterType type)
245{
246   // must match GFXAdapterType order
247   static const char* _names[] = { "OpenGL", "D3D11", "NullDevice" };
248   
249   if( type < 0 || type >= GFXAdapterType_Count )
250   {
251      Con::errorf( "GFXInit::getAdapterNameFromType - Invalid renderer type, defaulting to OpenGL" );
252      return _names[OpenGL];
253   }
254      
255   return _names[type];
256}
257
258GFXAdapterType GFXInit::getAdapterTypeFromName(const char* name)
259{
260   S32 ret = -1;
261   for(S32 i = 0; i < GFXAdapterType_Count; i++)
262   {
263      if( !dStricmp( getAdapterNameFromType((GFXAdapterType)i), name ) )
264         ret = i;
265   }
266   
267   if( ret == -1 )
268   {
269      Con::errorf( "GFXInit::getAdapterTypeFromName - Invalid renderer name, defaulting to D3D11" );
270      ret = Direct3D11;
271   }
272   
273   return (GFXAdapterType)ret;
274}
275
276GFXAdapter *GFXInit::getBestAdapterChoice()
277{
278   // Get the user's preference for device...
279   const String   renderer   = Con::getVariable("$pref::Video::displayDevice");
280   const String   outputDevice = Con::getVariable("$pref::Video::displayOutputDevice");
281   const String   adapterDevice = Con::getVariable("$Video::forceDisplayAdapter");
282
283   GFXAdapterType adapterType = getAdapterTypeFromName(renderer.c_str());;
284   GFXAdapter     *adapter = NULL;
285
286   if (adapterDevice.isEmpty())
287   {
288      adapter = chooseAdapter(adapterType, outputDevice.c_str());
289   }
290   else
291   {
292     S32 adapterIdx = dAtoi(adapterDevice.c_str());
293     if (adapterIdx == -1)
294        adapter = chooseAdapter(adapterType, outputDevice.c_str());
295     else
296        adapter = chooseAdapter(adapterType, adapterIdx);
297   }
298
299   // Did they have one? Return it.
300   if(adapter)
301      return adapter;
302
303   // Didn't have one. So make it up. Find the highest SM available. Prefer
304   // D3D to GL because if we have a D3D device at all we're on windows,
305   // and in an unknown situation on Windows D3D is probably the safest bet.
306   //
307   // If D3D is unavailable, we're not on windows, so GL is de facto the
308   // best choice!
309   F32 highestSMDX = 0.f, highestSMGL = 0.f;
310   GFXAdapter *foundAdapterGL = NULL, *foundAdapter11 = NULL;
311
312   for (S32 i = 0; i<smAdapters.size(); i++)
313   {
314      GFXAdapter *currAdapter = smAdapters[i];
315      switch (currAdapter->mType)
316      {
317      case Direct3D11:
318         if (currAdapter->mShaderModel > highestSMDX)
319         {
320            highestSMDX = currAdapter->mShaderModel;
321            foundAdapter11 = currAdapter;
322         }
323         break;
324      case OpenGL:
325         if (currAdapter->mShaderModel > highestSMGL)
326         {
327            highestSMGL = currAdapter->mShaderModel;
328            foundAdapterGL = currAdapter;
329         }
330         break;
331
332      default:
333         break;
334      }
335   }
336
337   // Return best found in order DX11, GL
338   if (foundAdapter11)
339      return foundAdapter11;
340
341   if (foundAdapterGL)
342      return foundAdapterGL;
343
344   // Uh oh - we didn't find anything. Grab whatever we can that's not Null...
345   for(S32 i=0; i<smAdapters.size(); i++)
346      if(smAdapters[i]->mType != NullDevice)
347         return smAdapters[i];
348
349   // Dare we return a null device? No. Just return NULL.
350   return NULL;
351}
352
353GFXVideoMode GFXInit::getInitialVideoMode()
354{
355   GFXVideoMode vm;
356   _GFXInitGetInitialRes(vm);
357   return vm;
358}
359
360S32 GFXInit::getAdapterCount()
361{
362   return smAdapters.size();
363}
364
365void GFXInit::getAdapters(Vector<GFXAdapter*> *adapters)
366{
367   adapters->clear();
368   for (U32 k = 0; k < smAdapters.size(); k++)
369      adapters->push_back(smAdapters[k]);
370}
371
372GFXVideoMode GFXInit::getDesktopResolution()
373{
374   GFXVideoMode resVm;
375
376   // Retrieve Resolution Information.
377   resVm.bitDepth    = WindowManager->getDesktopBitDepth();
378   resVm.resolution  = WindowManager->getDesktopResolution();
379   resVm.fullScreen  = false;
380   resVm.refreshRate = 60;
381
382   // Return results
383   return resVm;
384}
385
386void GFXInit::enumerateAdapters() 
387{
388   // Call each device class and have it report any adapters it supports.
389   if(smAdapters.size())
390   {
391      // CodeReview Seems like this is ok to just ignore? [bjg, 5/19/07]
392      //Con::warnf("GFXInit::enumerateAdapters - already have a populated adapter list, aborting re-analysis.");
393      return;
394   }
395
396   getRegisterDeviceSignal().trigger(GFXInit::smAdapters);     
397}
398
399GFXDevice *GFXInit::createDevice( GFXAdapter *adapter ) 
400{
401   Con::printf("Attempting to create GFX device: %s [%s]", adapter->getName(), adapter->getOutputName());
402
403   GFXDevice* temp = adapter->mCreateDeviceInstanceDelegate(adapter->mIndex);
404   if (temp)
405   {
406      Con::printf("Device created, setting adapter and enumerating modes");
407      temp->setAdapter(*adapter);
408      temp->enumerateVideoModes();
409      temp->getVideoModeList();
410   }
411   else
412      Con::errorf("Failed to create GFX device");
413
414   GFXDevice::getDeviceEventSignal().trigger(GFXDevice::deCreate);
415
416   return temp;
417}
418
419
420DefineEngineFunction( getDesktopResolution, Point3F, (),,
421   "Returns the width, height, and bitdepth of the screen/desktop.\n\n@ingroup GFX" )
422{
423   GFXVideoMode res = GFXInit::getDesktopResolution();
424   return Point3F( res.resolution.x, res.resolution.y, res.bitDepth );
425}
426
427DefineEngineStaticMethod( GFXInit, getAdapterCount, S32, (),,
428   "Return the number of graphics adapters available. @ingroup GFX")
429{
430   return GFXInit::getAdapterCount();
431}
432
433DefineEngineStaticMethod( GFXInit, getAdapterName, String, ( S32 index ),,
434   "Returns the name of the graphics adapter.\n"
435   "@param index The index of the adapter." )
436{
437   Vector<GFXAdapter*> adapters( __FILE__, __LINE__ );
438   GFXInit::getAdapters(&adapters);
439
440   if(index >= 0 && index < adapters.size())
441      return adapters[index]->mName;
442
443   Con::errorf( "GFXInit::getAdapterName - Out of range adapter index." );
444   return String::EmptyString;
445}
446
447DefineEngineStaticMethod( GFXInit, getAdapterOutputName, String, ( S32 index ),,
448   "Returns the name of the graphics adapter's output display device.\n"
449   "@param index The index of the adapter." )
450{
451   Vector<GFXAdapter*> adapters( __FILE__, __LINE__ );
452   GFXInit::getAdapters(&adapters);
453
454   if(index >= 0 && index < adapters.size())
455      return adapters[index]->mOutputName;
456
457   Con::errorf( "GFXInit::getAdapterOutputName - Out of range adapter index." );
458   return String::EmptyString;
459}
460
461DefineEngineStaticMethod( GFXInit, getAdapterType, GFXAdapterType, ( S32 index ),,
462   "Returns the type (D3D11, GL, Null) of a graphics adapter.\n"
463   "@param index The index of the adapter." )
464{
465   Vector<GFXAdapter*> adapters( __FILE__, __LINE__ );
466   GFXInit::getAdapters(&adapters);
467
468   if( index >= 0 && index < adapters.size())
469      return adapters[index]->mType;
470
471   Con::errorf( "GFXInit::getAdapterType - Out of range adapter index." );
472   return GFXAdapterType_Count;
473}
474
475DefineEngineStaticMethod( GFXInit, getAdapterShaderModel, F32, ( S32 index ),,
476   "Returns the supported shader model of the graphics adapter or -1 if the index is bad.\n"
477   "@param index The index of the adapter." )
478{
479   Vector<GFXAdapter*> adapters( __FILE__, __LINE__ );
480   GFXInit::getAdapters(&adapters);
481
482   if(index < 0 || index >= adapters.size())
483   {
484      Con::errorf("GFXInit::getAdapterShaderModel - Out of range adapter index.");
485      return -1.0f;
486   }
487
488   return adapters[index]->mShaderModel;
489}
490
491DefineEngineStaticMethod( GFXInit, getDefaultAdapterIndex, S32, (),,
492   "Returns the index of the default graphics adapter.  This is the graphics device "
493   "which will be used to initialize the engine." )
494{
495   GFXAdapter *a = GFXInit::getBestAdapterChoice();
496
497   // We have to find the index of the adapter in the list to
498   // return an index that makes sense to the script.
499   Vector<GFXAdapter*> adapters( __FILE__, __LINE__ );
500   GFXInit::getAdapters(&adapters);
501   for(S32 i=0; i<adapters.size(); i++)
502      if (  adapters[i]->mIndex == a->mIndex && 
503            adapters[i]->mType == a->mType )
504         return i;
505
506   Con::warnf( "GFXInit::getDefaultAdapterIndex - Didn't find the adapter in the list!" );
507   return -1;
508}
509
510DefineEngineStaticMethod( GFXInit, getAdapterModeCount, S32, ( S32 index ),,
511   "Gets the number of modes available on the specified adapter.\n\n"
512   "@param index Index of the adapter to get modes from.\n"
513   "@return The number of video modes supported by the adapter or -1 if the given adapter was not found." )
514{
515   Vector<GFXAdapter*> adapters( __FILE__, __LINE__ );
516   GFXInit::getAdapters(&adapters);
517
518   if( index < 0 || index >= adapters.size())
519   {
520      Con::warnf( "GFXInit::getAdapterModeCount - The index was out of range." );
521      return -1;
522   }
523
524   return adapters[index]->mAvailableModes.size();
525}
526
527DefineEngineStaticMethod( GFXInit, getAdapterMode, String, ( S32 index, S32 modeIndex ),,
528   "Gets the details of the specified adapter mode.\n\n"
529   "@param index Index of the adapter to query.\n"
530   "@param modeIndex Index of the mode to get data from.\n"
531   "@return A video mode string in the format 'width height fullscreen bitDepth refreshRate aaLevel'.\n"
532   "@see GuiCanvas::getVideoMode()" )
533{
534   Vector<GFXAdapter*> adapters( __FILE__, __LINE__ );
535   GFXInit::getAdapters(&adapters);
536
537   if ( index < 0 || index >= adapters.size() )
538   {
539      Con::warnf( "GFXInit::getAdapterMode - The adapter index was out of range." );
540      return String::EmptyString;
541   }
542
543   if ( modeIndex < 0 || modeIndex >= adapters[index]->mAvailableModes.size() )
544   {
545      Con::warnf( "GFXInit::getAdapterMode - The mode index was out of range." );
546      return String::EmptyString;
547   }
548
549   const GFXVideoMode &vm = adapters[index]->mAvailableModes[modeIndex];
550   return vm.toString();
551}
552
553DefineEngineStaticMethod( GFXInit, createNullDevice, void, (),,
554   "Create the NULL graphics device used for testing or headless operation." )
555{
556   // Enumerate things for GFX before we have an active device.
557   GFXInit::enumerateAdapters();
558 
559   // Create a device.
560   GFXAdapter *a = GFXInit::chooseAdapter(NullDevice, "");
561 
562   GFXDevice *newDevice = GFX;
563 
564   // Do we have a global device already? (This is the site if you want
565   // to start rendering to multiple devices simultaneously)
566   if(newDevice == NULL)
567      newDevice = GFXInit::createDevice(a);
568 
569   newDevice->setAllowRender( false );
570}
571