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