winOGLVideo.cc 44 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2013 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "platformWin32/platformGL.h"
  23. #include "platformWin32/platformWin32.h"
  24. #include "platformWin32/winOGLVideo.h"
  25. #include "console/console.h"
  26. #include "math/mPoint.h"
  27. #include "platform/event.h"
  28. #include "game/gameInterface.h"
  29. #include "console/consoleInternal.h"
  30. #include "console/ast.h"
  31. #include "io/fileStream.h"
  32. //------------------------------------------------------------------------------
  33. struct CardProfile
  34. {
  35. const char *vendor; // manufacturer
  36. const char *renderer; // driver name
  37. bool safeMode; // destroy rendering context for resolution change
  38. bool lockArray; // allow compiled vertex arrays
  39. bool subImage; // allow glTexSubImage*
  40. bool fogTexture; // require bound texture for combine extension
  41. bool noEnvColor; // no texture environment color
  42. bool clipHigh; // clip high resolutions
  43. bool deleteContext; // delete rendering context
  44. bool texCompress; // allow texture compression
  45. bool interiorLock; // lock arrays for Interior render
  46. bool skipFirstFog; // skip first two-pass fogging (dumb 3Dfx hack)
  47. bool only16; // inhibit 32-bit resolutions
  48. bool noArraysAlpha; // don't use glDrawArrays with a GL_ALPHA texture
  49. const char *proFile; // explicit profile of graphic settings
  50. };
  51. struct OSCardProfile
  52. {
  53. const char *vendor; // manufacturer
  54. const char *renderer; // driver name
  55. bool allowOpenGL; // allow OpenGL driver
  56. bool preferOpenGL; // prefer OpenGL driver
  57. };
  58. static Vector<CardProfile> sCardProfiles(__FILE__, __LINE__);
  59. static Vector<OSCardProfile> sOSCardProfiles(__FILE__, __LINE__);
  60. struct ProcessorProfile
  61. {
  62. U16 clock; // clock range max
  63. U16 adjust; // CPU adjust
  64. };
  65. static U8 sNumProcessors = 4;
  66. static ProcessorProfile sProcessorProfiles[] =
  67. {
  68. { 400, 0 },
  69. { 600, 5 },
  70. { 800, 10 },
  71. { 1000, 15 },
  72. };
  73. struct SettingProfile
  74. {
  75. U16 performance; // metric range max
  76. const char *settings; // default file
  77. };
  78. static U8 sNumSettings = 3;
  79. static SettingProfile sSettingProfiles[] =
  80. {
  81. { 33, "LowProfile.cs" },
  82. { 66, "MediumProfile.cs" },
  83. { 100, "HighProfile.cs" },
  84. };
  85. //------------------------------------------------------------------------------
  86. ConsoleFunction( addCardProfile, void, 16, 16, "(string vendor, string renderer,"
  87. "bool safeMode, bool lockArray, bool subImage, bool fogTexture,"
  88. "bool noEnvColor, bool clipHigh, bool deleteContext, bool texCompress"
  89. "bool interiorLock, bool skipFirstFog, bool only16,"
  90. "bool noArraysAlpha, string proFile)"
  91. ""
  92. "Register a card profile with the card profile manager.\n\n"
  93. "Most of the parameters are fairly self-explanatory and very internal"
  94. " to the rendering code; however there are a few of note:\n"
  95. "@param vendor The vendor string the card claims.\n"
  96. "@param renderer The renderer string the card claims.\n"
  97. "@param proFile Name of the file where further configuration information is kept."
  98. )
  99. {
  100. CardProfile profile;
  101. profile.vendor = dStrdup(argv[1]);
  102. profile.renderer = dStrdup(argv[2]);
  103. profile.safeMode = dAtob(argv[3]);
  104. profile.lockArray = dAtob(argv[4]);
  105. profile.subImage = dAtob(argv[5]);
  106. profile.fogTexture = dAtob(argv[6]);
  107. profile.noEnvColor = dAtob(argv[7]);
  108. profile.clipHigh = dAtob(argv[8]);
  109. profile.deleteContext = dAtob(argv[9]);
  110. profile.texCompress = dAtob(argv[10]);
  111. profile.interiorLock = dAtob(argv[11]);
  112. profile.skipFirstFog = dAtob(argv[12]);
  113. profile.only16 = dAtob(argv[13]);
  114. profile.noArraysAlpha = dAtob(argv[14]);
  115. if (strcmp(argv[15],""))
  116. profile.proFile = dStrdup(argv[15]);
  117. else
  118. profile.proFile = NULL;
  119. sCardProfiles.push_back(profile);
  120. }
  121. ConsoleFunction( addOSCardProfile, void, 6,6, "(string vendor, string renderer, bool allowOpenGL,"
  122. "Register with the profile manager what rendering mode is preferred with the "
  123. "specified card.")
  124. {
  125. OSCardProfile profile;
  126. profile.vendor = dStrdup(argv[1]);
  127. profile.renderer = dStrdup(argv[2]);
  128. profile.allowOpenGL = dAtob(argv[3]);
  129. profile.preferOpenGL = dAtob(argv[5]);
  130. sOSCardProfiles.push_back(profile);
  131. }
  132. static void clearCardProfiles()
  133. {
  134. while (sCardProfiles.size())
  135. {
  136. dFree((char *) sCardProfiles.last().vendor);
  137. dFree((char *) sCardProfiles.last().renderer);
  138. dFree((char *) sCardProfiles.last().proFile);
  139. sCardProfiles.decrement();
  140. }
  141. }
  142. static void clearOSCardProfiles()
  143. {
  144. while (sOSCardProfiles.size())
  145. {
  146. dFree((char *) sOSCardProfiles.last().vendor);
  147. dFree((char *) sOSCardProfiles.last().renderer);
  148. sOSCardProfiles.decrement();
  149. }
  150. }
  151. static void execScript(const char *scriptFile)
  152. {
  153. // execute the script
  154. FileStream str;
  155. if (!str.open(scriptFile, FileStream::Read))
  156. return;
  157. U32 size = str.getStreamSize();
  158. char *script = new char[size + 1];
  159. str.read(size, script);
  160. str.close();
  161. script[size] = 0;
  162. Con::executef(2, "eval", script);
  163. delete[] script;
  164. }
  165. static void profileSystem(const char *vendor, const char *renderer)
  166. {
  167. //Con::executef(2, "exec", "scripts/CardProfiles.cs");
  168. execScript("CardProfiles.cs");
  169. const char *arch;
  170. OSVERSIONINFO OSVersionInfo;
  171. const char *os = NULL;
  172. char osProfiles[64];
  173. if (dStrstr(PlatformSystemInfo.processor.name,"AMD") != NULL)
  174. arch = "AMD";
  175. else
  176. arch = "Intel";
  177. dMemset( &OSVersionInfo, 0, sizeof( OSVERSIONINFO ) );
  178. OSVersionInfo.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
  179. if ( GetVersionEx( &OSVersionInfo ) )
  180. {
  181. if (OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
  182. if ( OSVersionInfo.dwMinorVersion == 0 )
  183. {
  184. if (dStrcmp(arch,"Intel") == 0)
  185. os = "W95";
  186. }
  187. else if ( OSVersionInfo.dwMinorVersion == 10 )
  188. if ( OSVersionInfo.szCSDVersion[1] != 'A' )
  189. os = "W98";
  190. else
  191. os = "W98SE";
  192. else
  193. os = "WME";
  194. else
  195. if ( OSVersionInfo.dwMajorVersion >= 5 )
  196. os = "W2K";
  197. if ( os != NULL )
  198. {
  199. dSprintf(osProfiles,64,"%s%sCardProfiles.cs",arch,os);
  200. //Con::executef(2, "exec", osProfiles);
  201. execScript(osProfiles);
  202. }
  203. }
  204. const char *proFile = NULL;
  205. U32 i;
  206. for (i = 0; i < (U32)sCardProfiles.size(); ++i)
  207. if (dStrstr(vendor, sCardProfiles[i].vendor) &&
  208. (!dStrcmp(sCardProfiles[i].renderer, "*") ||
  209. dStrstr(renderer, sCardProfiles[i].renderer)))
  210. {
  211. Con::setBoolVariable("$pref::Video::safeModeOn", sCardProfiles[i].safeMode);
  212. Con::setBoolVariable("$pref::OpenGL::disableEXTCompiledVertexArray", !sCardProfiles[i].lockArray);
  213. Con::setBoolVariable("$pref::OpenGL::disableSubImage", !sCardProfiles[i].subImage);
  214. Con::setBoolVariable("$pref::TS::fogTexture", sCardProfiles[i].fogTexture);
  215. Con::setBoolVariable("$pref::OpenGL::noEnvColor", sCardProfiles[i].noEnvColor);
  216. Con::setBoolVariable("$pref::Video::clipHigh", sCardProfiles[i].clipHigh);
  217. if (!sCardProfiles[i].deleteContext)
  218. {
  219. OSVERSIONINFO OSVersionInfo;
  220. // HACK: The Voodoo3/5 on W2K crash when deleting a rendering context
  221. // So we're not deleting it.
  222. // Oh, and the Voodoo3 returns a Banshee renderer string under W2K
  223. dMemset( &OSVersionInfo, 0, sizeof( OSVERSIONINFO ) );
  224. OSVersionInfo.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
  225. if ( GetVersionEx( &OSVersionInfo ) &&
  226. OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT &&
  227. OSVersionInfo.dwMajorVersion == 5)
  228. Con::setBoolVariable("$pref::Video::deleteContext", false);
  229. else
  230. Con::setBoolVariable("$pref::Video::deleteContext", true);
  231. }
  232. else
  233. Con::setBoolVariable("$pref::Video::deleteContext", true);
  234. Con::setBoolVariable("$pref::OpenGL::disableARBTextureCompression", !sCardProfiles[i].texCompress);
  235. Con::setBoolVariable("$pref::Interior::lockArrays", sCardProfiles[i].interiorLock);
  236. Con::setBoolVariable("$pref::TS::skipFirstFog", sCardProfiles[i].skipFirstFog);
  237. Con::setBoolVariable("$pref::Video::only16", sCardProfiles[i].only16);
  238. Con::setBoolVariable("$pref::OpenGL::noDrawArraysAlpha", sCardProfiles[i].noArraysAlpha);
  239. proFile = sCardProfiles[i].proFile;
  240. break;
  241. }
  242. // defaults
  243. U16 glProfile;
  244. if (!proFile)
  245. {
  246. // no driver GL profile -- make one via weighting GL extensions
  247. glProfile = 25;
  248. glProfile += gGLState.suppARBMultitexture * 25;
  249. glProfile += gGLState.suppLockedArrays * 15;
  250. glProfile += gGLState.suppVertexArrayRange * 10;
  251. glProfile += gGLState.suppTextureEnvCombine * 5;
  252. glProfile += gGLState.suppPackedPixels * 5;
  253. glProfile += gGLState.suppTextureCompression * 5;
  254. glProfile += gGLState.suppS3TC * 5;
  255. glProfile += gGLState.suppFXT1 * 5;
  256. Con::setBoolVariable("$pref::Video::safeModeOn", true);
  257. Con::setBoolVariable("$pref::OpenGL::disableEXTCompiledVertexArray", false);
  258. Con::setBoolVariable("$pref::OpenGL::disableSubImage", false);
  259. Con::setBoolVariable("$pref::TS::fogTexture", false);
  260. Con::setBoolVariable("$pref::OpenGL::noEnvColor", false);
  261. Con::setBoolVariable("$pref::Video::clipHigh", false);
  262. Con::setBoolVariable("$pref::Video::deleteContext", true);
  263. Con::setBoolVariable("$pref::OpenGL::disableARBTextureCompression", false);
  264. Con::setBoolVariable("$pref::Interior::lockArrays", true);
  265. Con::setBoolVariable("$pref::TS::skipFirstFog", false);
  266. Con::setBoolVariable("$pref::Video::only16", false);
  267. Con::setBoolVariable("$pref::OpenGL::noDrawArraysAlpha", false);
  268. }
  269. Con::setVariable("$pref::Video::profiledVendor", vendor);
  270. Con::setVariable("$pref::Video::profiledRenderer", renderer);
  271. if (!Con::getBoolVariable("$DisableSystemProfiling") &&
  272. ( dStrcmp(vendor, Con::getVariable("$pref::Video::defaultsVendor")) ||
  273. dStrcmp(renderer, Con::getVariable("$pref::Video::defaultsRenderer")) ))
  274. {
  275. if (proFile)
  276. {
  277. char settings[64];
  278. dSprintf(settings,64,"%s.cs",proFile);
  279. //Con::executef(2, "exec", settings);
  280. execScript(settings);
  281. }
  282. else
  283. {
  284. U16 adjust;
  285. // match clock with profile
  286. for (i = 0; i < sNumProcessors; ++i)
  287. {
  288. adjust = sProcessorProfiles[i].adjust;
  289. if (PlatformSystemInfo.processor.mhz < sProcessorProfiles[i].clock) break;
  290. }
  291. const char *settings;
  292. // match performance metric with profile
  293. for (i = 0; i < sNumSettings; ++i)
  294. {
  295. settings = sSettingProfiles[i].settings;
  296. if (glProfile+adjust <= sSettingProfiles[i].performance) break;
  297. }
  298. //Con::executef(2, "exec", settings);
  299. execScript(settings);
  300. }
  301. bool match = false;
  302. for (i = 0; i < (U32)sOSCardProfiles.size(); ++i)
  303. if (dStrstr(vendor, sOSCardProfiles[i].vendor) &&
  304. (!dStrcmp(sOSCardProfiles[i].renderer, "*") ||
  305. dStrstr(renderer, sOSCardProfiles[i].renderer)))
  306. {
  307. Con::setBoolVariable("$pref::Video::allowOpenGL", sOSCardProfiles[i].allowOpenGL);
  308. Con::setBoolVariable("$pref::Video::preferOpenGL", sOSCardProfiles[i].preferOpenGL);
  309. match = true;
  310. break;
  311. }
  312. if (!match)
  313. {
  314. Con::setBoolVariable("$pref::Video::allowOpenGL", true);
  315. Con::setBoolVariable("$pref::Video::preferOpenGL", true);
  316. }
  317. Con::setVariable("$pref::Video::defaultsVendor", vendor);
  318. Con::setVariable("$pref::Video::defaultsRenderer", renderer);
  319. }
  320. clearCardProfiles();
  321. clearOSCardProfiles();
  322. }
  323. //------------------------------------------------------------------------------
  324. OpenGLDevice::OpenGLDevice()
  325. {
  326. initDevice();
  327. }
  328. //------------------------------------------------------------------------------
  329. void OpenGLDevice::initDevice()
  330. {
  331. // Set the device name:
  332. mDeviceName = "OpenGL";
  333. // Let Parent enumerate valid resolutions.
  334. Parent::initDevice();
  335. }
  336. //------------------------------------------------------------------------------
  337. bool OpenGLDevice::activate( U32 width, U32 height, U32 bpp, bool fullScreen )
  338. {
  339. Con::printf( "Activating the OpenGL display device..." );
  340. bool needResurrect = false;
  341. // If the rendering context exists, delete it:
  342. if ( winState.hGLRC )
  343. {
  344. Con::printf( "Killing the texture manager..." );
  345. Game->textureKill();
  346. needResurrect = true;
  347. Con::printf( "Making the rendering context not current..." );
  348. if ( !dwglMakeCurrent( NULL, NULL ) )
  349. {
  350. AssertFatal( false, "OpenGLDevice::activate\ndwglMakeCurrent( NULL, NULL ) failed!" );
  351. return false;
  352. }
  353. Con::printf( "Deleting the rendering context ..." );
  354. if ( !dwglDeleteContext( winState.hGLRC ) )
  355. {
  356. AssertFatal( false, "OpenGLDevice::activate\ndwglDeleteContext failed!" );
  357. return false;
  358. }
  359. winState.hGLRC = NULL;
  360. }
  361. // [neo, 5/31/2007 - #3174]
  362. if( winState.appMenu )
  363. {
  364. DestroyMenu( winState.appMenu );
  365. winState.appMenu = NULL;
  366. }
  367. // If the window already exists, kill it so we can start fresh:
  368. if ( winState.appWindow )
  369. {
  370. if ( winState.appDC )
  371. {
  372. Con::printf( "Releasing the device context..." );
  373. ReleaseDC( winState.appWindow, winState.appDC );
  374. winState.appDC = NULL;
  375. }
  376. Con::printf( "Destroying the window..." );
  377. DestroyWindow( winState.appWindow );
  378. winState.appWindow = NULL;
  379. }
  380. // If OpenGL library already loaded, shut it down and reload it:
  381. if ( winState.hinstOpenGL )
  382. GL_Shutdown();
  383. GL_Init( "opengl32", "glu32" );
  384. static bool onceAlready = false;
  385. bool profiled = false;
  386. if ( !mFullScreenOnly && fullScreen && !onceAlready )
  387. {
  388. OSVERSIONINFO OSVersionInfo;
  389. // HACK: The Voodoo5 on W2K will only work if the initial rendering
  390. // context is windowed. Can you believe this crap?
  391. dMemset( &OSVersionInfo, 0, sizeof( OSVERSIONINFO ) );
  392. OSVersionInfo.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
  393. if ( GetVersionEx( &OSVersionInfo ) &&
  394. OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT &&
  395. OSVersionInfo.dwMajorVersion == 5 )
  396. //MIN_RESOLUTION defined in platformWin32/platformGL.h
  397. if ( !setScreenMode( MIN_RESOLUTION_X, MIN_RESOLUTION_Y, bpp, false, true, false ) )
  398. return false;
  399. else
  400. {
  401. const char* vendorString = (const char*) glGetString( GL_VENDOR );
  402. const char* rendererString = (const char*) glGetString( GL_RENDERER );
  403. // only do this for the first session
  404. if (!Con::getBoolVariable("$DisableSystemProfiling") &&
  405. ( dStrcmp(vendorString, Con::getVariable("$pref::Video::profiledVendor")) ||
  406. dStrcmp(rendererString, Con::getVariable("$pref::Video::profiledRenderer")) ))
  407. {
  408. profileSystem(vendorString, rendererString);
  409. profiled = true;
  410. }
  411. }
  412. onceAlready = true;
  413. }
  414. // Set the resolution:
  415. if ( !setScreenMode( width, height, bpp, ( fullScreen || mFullScreenOnly ), true, false ) )
  416. return false;
  417. // Get original gamma ramp
  418. mRestoreGamma = GetDeviceGammaRamp(winState.appDC, mOriginalRamp);
  419. // Output some driver info to the console:
  420. const char* vendorString = (const char*) glGetString( GL_VENDOR );
  421. const char* rendererString = (const char*) glGetString( GL_RENDERER );
  422. const char* versionString = (const char*) glGetString( GL_VERSION );
  423. Con::printf( "OpenGL driver information:" );
  424. if ( vendorString )
  425. Con::printf( " Vendor: %s", vendorString );
  426. if ( rendererString )
  427. Con::printf( " Renderer: %s", rendererString );
  428. if ( versionString )
  429. Con::printf( " Version: %s", versionString );
  430. if ( needResurrect )
  431. {
  432. // Reload the textures:
  433. Con::printf( "Resurrecting the texture manager..." );
  434. Game->textureResurrect();
  435. }
  436. GL_EXT_Init();
  437. Con::setVariable( "$pref::Video::displayDevice", mDeviceName );
  438. // only do this for the first session
  439. if (!profiled &&
  440. !Con::getBoolVariable("$DisableSystemProfiling") &&
  441. ( dStrcmp(vendorString, Con::getVariable("$pref::Video::profiledVendor")) ||
  442. dStrcmp(rendererString, Con::getVariable("$pref::Video::profiledRenderer")) ))
  443. {
  444. profileSystem(vendorString, rendererString);
  445. profiled = true;
  446. }
  447. if (profiled)
  448. {
  449. U32 width, height, bpp;
  450. if (Con::getBoolVariable("$pref::Video::clipHigh", false))
  451. for (S32 i = mResolutionList.size()-1; i >= 0; --i)
  452. if (mResolutionList[i].w > 1152 || mResolutionList[i].h > 864)
  453. mResolutionList.erase(i);
  454. if (Con::getBoolVariable("$pref::Video::only16", false))
  455. for (S32 i = mResolutionList.size()-1; i >= 0; --i)
  456. if (mResolutionList[i].bpp == 32)
  457. mResolutionList.erase(i);
  458. bool bPrefFullScreen = Con::getBoolVariable("$pref::Video::fullScreen", true);
  459. if( bPrefFullScreen || fullScreen )
  460. dSscanf(Con::getVariable("$pref::Video::resolution"), "%d %d %d", &width, &height, &bpp);
  461. else
  462. dSscanf(Con::getVariable("$pref::Video::windowedRes"), "%d %d %d", &width, &height, &bpp);
  463. setScreenMode(width, height, bpp,
  464. bPrefFullScreen || fullScreen, false, false);
  465. }
  466. // Do this here because we now know about the extensions:
  467. if ( gGLState.suppSwapInterval )
  468. setVerticalSync( !Con::getBoolVariable( "$pref::Video::disableVerticalSync" ) );
  469. Con::setBoolVariable("$pref::OpenGL::allowTexGen", true);
  470. return true;
  471. }
  472. //------------------------------------------------------------------------------
  473. void OpenGLDevice::shutdown()
  474. {
  475. Con::printf( "Shutting down the OpenGL display device..." );
  476. if ( winState.hGLRC )
  477. {
  478. if (mRestoreGamma)
  479. SetDeviceGammaRamp(winState.appDC, mOriginalRamp);
  480. Con::printf( "Making the GL rendering context not current..." );
  481. dwglMakeCurrent( NULL, NULL );
  482. if ( Con::getBoolVariable("$pref::Video::deleteContext", true) )
  483. {
  484. Con::printf( "Deleting the GL rendering context..." );
  485. dwglDeleteContext( winState.hGLRC );
  486. }
  487. winState.hGLRC = NULL;
  488. }
  489. if ( winState.appDC )
  490. {
  491. Con::printf( "Releasing the device context..." );
  492. ReleaseDC( winState.appWindow, winState.appDC );
  493. winState.appDC = NULL;
  494. }
  495. if ( smIsFullScreen )
  496. {
  497. Con::printf( "Restoring the desktop display settings (%dx%dx%d)...", winState.desktopWidth, winState.desktopHeight, winState.desktopBitsPixel );
  498. ChangeDisplaySettings( NULL, 0 );
  499. }
  500. }
  501. //------------------------------------------------------------------------------
  502. // This is the real workhorse function of the DisplayDevice...
  503. //
  504. bool OpenGLDevice::setScreenMode( U32 width, U32 height, U32 bpp, bool fullScreen, bool forceIt, bool repaint )
  505. {
  506. HWND curtain = NULL;
  507. char errorMessage[256];
  508. Resolution newRes( width, height, bpp );
  509. bool newFullScreen = fullScreen;
  510. bool safeModeOn = Con::getBoolVariable( "$pref::Video::safeModeOn" );
  511. if ( !newFullScreen && mFullScreenOnly )
  512. {
  513. Con::warnf( ConsoleLogEntry::General, "OpenGLDevice::setScreenMode - device or desktop color depth does not allow windowed mode!" );
  514. newFullScreen = true;
  515. }
  516. if ( !newFullScreen && ( (S32)newRes.w >= winState.desktopClientWidth || (S32)newRes.h >= winState.desktopClientHeight ) )
  517. {
  518. Con::warnf( ConsoleLogEntry::General, "OpenGLDevice::setScreenMode -- can't switch to resolution larger than desktop in windowed mode!" );
  519. S32 resIndex = 0;
  520. S32 bestScore = 0, thisScore = 0;
  521. for ( S32 i = 0; i < mResolutionList.size(); i++ )
  522. {
  523. if ( newRes == mResolutionList[i] )
  524. {
  525. resIndex = i;
  526. break;
  527. }
  528. else if( (S32)newRes.h <= winState.desktopClientHeight && (S32)newRes.w <= winState.desktopClientWidth )
  529. {
  530. thisScore = abs( S32( newRes.w ) - S32( mResolutionList[i].w ) )
  531. + abs( S32( newRes.h ) - S32( mResolutionList[i].h ) )
  532. + ( newRes.bpp == mResolutionList[i].bpp ? 0 : 1 );
  533. if ( !bestScore || ( thisScore < bestScore ) )
  534. {
  535. bestScore = thisScore;
  536. resIndex = i;
  537. }
  538. }
  539. }
  540. }
  541. //MIN_RESOLUTION defined in platformWin32/platformGL.h
  542. if ( newRes.w < MIN_RESOLUTION_X || newRes.h < MIN_RESOLUTION_Y )
  543. {
  544. Con::warnf( ConsoleLogEntry::General, "OpenGLDevice::setScreenMode -- can't go smaller than 640x480!" );
  545. return false;
  546. }
  547. if ( newFullScreen )
  548. {
  549. if (newRes.bpp != 16 && mFullScreenOnly)
  550. newRes.bpp = 16;
  551. // Match the new resolution to one in the list:
  552. U32 resIndex = 0;
  553. U32 bestScore = 0, thisScore = 0;
  554. for ( int i = 0; i < mResolutionList.size(); i++ )
  555. {
  556. if ( newRes == mResolutionList[i] )
  557. {
  558. resIndex = i;
  559. break;
  560. }
  561. else
  562. {
  563. thisScore = abs( S32( newRes.w ) - S32( mResolutionList[i].w ) )
  564. + abs( S32( newRes.h ) - S32( mResolutionList[i].h ) )
  565. + ( newRes.bpp == mResolutionList[i].bpp ? 0 : 1 );
  566. if ( !bestScore || ( thisScore < bestScore ) )
  567. {
  568. bestScore = thisScore;
  569. resIndex = i;
  570. }
  571. }
  572. }
  573. newRes = mResolutionList[resIndex];
  574. }
  575. else
  576. {
  577. // Basically ignore the bit depth parameter:
  578. newRes.bpp = winState.desktopBitsPixel;
  579. }
  580. // Return if already at this resolution:
  581. if ( !forceIt && newRes == smCurrentRes && newFullScreen == smIsFullScreen )
  582. return true;
  583. Con::printf( "Setting screen mode to %dx%dx%d (%s)...", newRes.w, newRes.h, newRes.bpp, ( newFullScreen ? "fs" : "w" ) );
  584. bool needResurrect = false;
  585. if ( ( newRes.bpp != smCurrentRes.bpp ) || ( safeModeOn && ( ( smIsFullScreen != newFullScreen ) || newFullScreen ) ) )
  586. {
  587. // Delete the rendering context:
  588. if ( winState.hGLRC )
  589. {
  590. if (!Video::smNeedResurrect)
  591. {
  592. Con::printf( "Killing the texture manager..." );
  593. Game->textureKill();
  594. needResurrect = true;
  595. }
  596. Con::printf( "Making the rendering context not current..." );
  597. if ( !dwglMakeCurrent( NULL, NULL ) )
  598. {
  599. AssertFatal( false, "OpenGLDevice::setScreenMode\ndwglMakeCurrent( NULL, NULL ) failed!" );
  600. return false;
  601. }
  602. Con::printf( "Deleting the rendering context..." );
  603. if ( Con::getBoolVariable("$pref::Video::deleteContext",true) &&
  604. !dwglDeleteContext( winState.hGLRC ) )
  605. {
  606. AssertFatal( false, "OpenGLDevice::setScreenMode\ndwglDeleteContext failed!" );
  607. return false;
  608. }
  609. winState.hGLRC = NULL;
  610. }
  611. // Release the device context:
  612. if ( winState.appDC )
  613. {
  614. Con::printf( "Releasing the device context..." );
  615. ReleaseDC( winState.appWindow, winState.appDC );
  616. winState.appDC = NULL;
  617. }
  618. // [neo, 5/31/2007 - #3174]
  619. if( winState.appMenu )
  620. {
  621. DestroyMenu( winState.appMenu );
  622. winState.appMenu = NULL;
  623. }
  624. // Destroy the window:
  625. if ( winState.appWindow )
  626. {
  627. Con::printf( "Destroying the window..." );
  628. DestroyWindow( winState.appWindow );
  629. winState.appWindow = NULL;
  630. }
  631. }
  632. else if ( smIsFullScreen != newFullScreen )
  633. {
  634. // Change the window style:
  635. Con::printf( "Changing the window style..." );
  636. S32 windowStyle = WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
  637. if ( newFullScreen )
  638. windowStyle |= ( WS_MAXIMIZE | WS_VISIBLE);
  639. else
  640. windowStyle |= ( WS_OVERLAPPEDWINDOW );
  641. if ( winState.appWindow && !SetWindowLong( winState.appWindow, GWL_STYLE, windowStyle ) )
  642. Con::errorf( "SetWindowLong failed to change the window style!" );
  643. }
  644. if( winState.appWindow && !newFullScreen )
  645. ShowWindow( winState.appWindow, SW_NORMAL );
  646. else
  647. ShowWindow( winState.appWindow, SW_MAXIMIZE );
  648. U32 test;
  649. if ( newFullScreen )
  650. {
  651. // Change the display settings:
  652. DEVMODE devMode;
  653. dMemset( &devMode, 0, sizeof( devMode ) );
  654. devMode.dmSize = sizeof( devMode );
  655. devMode.dmPelsWidth = newRes.w;
  656. devMode.dmPelsHeight = newRes.h;
  657. devMode.dmBitsPerPel = newRes.bpp;
  658. devMode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
  659. Con::printf( "Changing the display settings to %dx%dx%d...", newRes.w, newRes.h, newRes.bpp );
  660. curtain = CreateCurtain( newRes.w, newRes.h );
  661. test = ChangeDisplaySettings( &devMode, CDS_FULLSCREEN );
  662. if ( test != DISP_CHANGE_SUCCESSFUL )
  663. {
  664. smIsFullScreen = false;
  665. Con::setBoolVariable( "$pref::Video::fullScreen", false );
  666. ChangeDisplaySettings( NULL, 0 );
  667. Con::errorf( ConsoleLogEntry::General, "OpenGLDevice::setScreenMode - ChangeDisplaySettings failed." );
  668. switch( test )
  669. {
  670. case DISP_CHANGE_RESTART:
  671. Platform::AlertOK( "Display Change Failed", "You must restart your machine to get the specified mode." );
  672. break;
  673. case DISP_CHANGE_BADMODE:
  674. Platform::AlertOK( "Display Change Failed", "The specified mode is not supported by this device." );
  675. break;
  676. default:
  677. Platform::AlertOK( "Display Change Failed", "Hardware failed to switch to the specified mode." );
  678. break;
  679. };
  680. DestroyWindow( curtain );
  681. return false;
  682. }
  683. else
  684. smIsFullScreen = true;
  685. }
  686. else if ( smIsFullScreen )
  687. {
  688. Con::printf( "Changing to the desktop display settings (%dx%dx%d)...", winState.desktopWidth, winState.desktopHeight, winState.desktopBitsPixel );
  689. ChangeDisplaySettings( NULL, 0 );
  690. smIsFullScreen = false;
  691. }
  692. Con::setBoolVariable( "$pref::Video::fullScreen", smIsFullScreen );
  693. bool newWindow = false;
  694. if ( !winState.appWindow )
  695. {
  696. Con::printf( "Creating a new %swindow...", ( fullScreen ? "full-screen " : "" ) );
  697. winState.appWindow = CreateOpenGLWindow( newRes.w, newRes.h, newFullScreen, true );
  698. if ( !winState.appWindow )
  699. {
  700. AssertFatal( false, "OpenGLDevice::setScreenMode\nFailed to create a new window!" );
  701. return false;
  702. }
  703. newWindow = true;
  704. }
  705. // Move the window:
  706. if ( !newFullScreen )
  707. {
  708. // Adjust the window rect to compensate for the window style:
  709. RECT windowRect;
  710. windowRect.left = windowRect.top = 0;
  711. windowRect.right = newRes.w;
  712. windowRect.bottom = newRes.h;
  713. AdjustWindowRect( &windowRect, GetWindowLong( winState.appWindow, GWL_STYLE ), false );
  714. U32 adjWidth = windowRect.right - windowRect.left;
  715. U32 adjHeight = windowRect.bottom - windowRect.top;
  716. // Center the window on the desktop:
  717. U32 xPos = 0, yPos = 0;
  718. if(adjWidth < (U32)winState.desktopClientWidth)
  719. xPos = ( winState.desktopClientWidth - adjWidth ) / 2;
  720. if(adjHeight < (U32)winState.desktopClientHeight)
  721. yPos = ( winState.desktopClientHeight - adjHeight ) / 2;
  722. test = SetWindowPos( winState.appWindow, 0, xPos, yPos, adjWidth, adjHeight, SWP_NOZORDER );
  723. if ( !test )
  724. {
  725. dSprintf( errorMessage, 255, "OpenGLDevice::setScreenMode\nSetWindowPos failed trying to move the window to (%d,%d) and size it to %dx%d.", xPos, yPos, newRes.w, newRes.h );
  726. AssertFatal( false, errorMessage );
  727. return false;
  728. }
  729. AnimateWindow( winState.appWindow, 90, AW_BLEND );
  730. }
  731. else if ( !newWindow )
  732. {
  733. // Move and size the window to take up the whole screen:
  734. if ( !SetWindowPos( winState.appWindow, HWND_TOPMOST, 0, 0, newRes.w, newRes.h, SWP_NOACTIVATE)
  735. || !SetWindowPos( winState.appWindow, HWND_TOPMOST, 0, 0, newRes.w, newRes.h, SWP_NOZORDER) )
  736. {
  737. dSprintf( errorMessage, 255, "OpenGLDevice::setScreenMode\nSetWindowPos failed to move the window to (0,0) and size it to %dx%d.", newRes.w, newRes.h );
  738. AssertFatal( false, errorMessage );
  739. return false;
  740. }
  741. }
  742. bool newDeviceContext = false;
  743. if ( !winState.appDC )
  744. {
  745. // Get a new device context:
  746. Con::printf( "Acquiring a new device context..." );
  747. winState.appDC = GetDC( winState.appWindow );
  748. if ( !winState.appDC )
  749. {
  750. AssertFatal( false, "OpenGLDevice::setScreenMode\nGetDC failed to get a valid device context!" );
  751. return false;
  752. }
  753. newDeviceContext = true;
  754. }
  755. if ( newWindow )
  756. {
  757. // Set the pixel format of the new window:
  758. PIXELFORMATDESCRIPTOR pfd;
  759. CreatePixelFormat( &pfd, newRes.bpp, 24, 8, false );
  760. S32 chosenFormat = ChooseBestPixelFormat( winState.appDC, &pfd );
  761. if ( !chosenFormat )
  762. {
  763. AssertFatal( false, "OpenGLDevice::setScreenMode\nNo valid pixel formats found!" );
  764. return false;
  765. }
  766. dwglDescribePixelFormat( winState.appDC, chosenFormat, sizeof( pfd ), &pfd );
  767. if ( !SetPixelFormat( winState.appDC, chosenFormat, &pfd ) )
  768. {
  769. AssertFatal( false, "OpenGLDevice::setScreenMode\nFailed to set the pixel format!" );
  770. return false;
  771. }
  772. Con::printf( "Pixel format set:" );
  773. Con::printf( " %d color bits, %d depth bits, %d stencil bits", pfd.cColorBits, pfd.cDepthBits, pfd.cStencilBits );
  774. }
  775. if ( !winState.hGLRC )
  776. {
  777. // Create a new rendering context:
  778. Con::printf( "Creating a new rendering context..." );
  779. winState.hGLRC = dwglCreateContext( winState.appDC );
  780. if ( !winState.hGLRC )
  781. {
  782. AssertFatal( false, "OpenGLDevice::setScreenMode\ndwglCreateContext failed to create an OpenGL rendering context!" );
  783. return false;
  784. }
  785. // Make the new rendering context current:
  786. Con::printf( "Making the new rendering context current..." );
  787. if ( !dwglMakeCurrent( winState.appDC, winState.hGLRC ) )
  788. {
  789. AssertFatal( false, "OpenGLDevice::setScreenMode\ndwglMakeCurrent failed to make the rendering context current!" );
  790. return false;
  791. }
  792. // Just for kicks. Seems a relatively central place to put this...
  793. glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  794. if ( needResurrect )
  795. {
  796. // Reload the textures:
  797. Con::printf( "Resurrecting the texture manager..." );
  798. Game->textureResurrect();
  799. }
  800. }
  801. // Just for kicks. Seems a relatively central place to put this...
  802. glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  803. if ( newDeviceContext && gGLState.suppSwapInterval )
  804. setVerticalSync( !Con::getBoolVariable( "$pref::Video::disableVerticalSync" ) );
  805. smCurrentRes = newRes;
  806. Platform::setWindowSize( newRes.w, newRes.h );
  807. char tempBuf[15];
  808. dSprintf( tempBuf, sizeof( tempBuf ), "%d %d %d", smCurrentRes.w, smCurrentRes.h, smCurrentRes.bpp );
  809. if( fullScreen )
  810. Con::setVariable( "$pref::Video::resolution", tempBuf );
  811. else
  812. Con::setVariable( "$pref::Video::windowedRes", tempBuf );
  813. if ( curtain )
  814. DestroyWindow( curtain );
  815. // Doesn't hurt to do this even it isn't necessary:
  816. ShowWindow( winState.appWindow, SW_SHOW );
  817. SetForegroundWindow( winState.appWindow );
  818. SetFocus( winState.appWindow );
  819. if (newFullScreen)
  820. {
  821. // Doesn't hurt to do this an extra time, and seems to help in some cases
  822. if ( !SetWindowPos( winState.appWindow, HWND_TOPMOST, 0, 0, newRes.w, newRes.h, SWP_NOACTIVATE)
  823. || !SetWindowPos( winState.appWindow, HWND_TOPMOST, 0, 0, newRes.w, newRes.h, SWP_NOZORDER) )
  824. {
  825. dSprintf( errorMessage, 255, "OpenGLDevice::setScreenMode\nSetWindowPos failed to move the window to (0,0) and size it to %dx%d.", newRes.w, newRes.h );
  826. AssertFatal( false, errorMessage );
  827. return false;
  828. }
  829. }
  830. //Luma: Clear window at first, as it is showing previous gl color buffer stuff.
  831. glClearColor(0.0f,0.0f,0.0f,0.0f);
  832. glClear(GL_COLOR_BUFFER_BIT);
  833. if ( repaint )
  834. Con::evaluate( "resetCanvas();" );
  835. return true;
  836. }
  837. //------------------------------------------------------------------------------
  838. void OpenGLDevice::swapBuffers()
  839. {
  840. dwglSwapBuffers( winState.appDC );
  841. }
  842. //------------------------------------------------------------------------------
  843. const char* OpenGLDevice::getDriverInfo()
  844. {
  845. // Output some driver info to the console:
  846. const char* vendorString = (const char*) glGetString( GL_VENDOR );
  847. const char* rendererString = (const char*) glGetString( GL_RENDERER );
  848. const char* versionString = (const char*) glGetString( GL_VERSION );
  849. const char* extensionsString = (const char*) glGetString( GL_EXTENSIONS );
  850. U32 bufferLen = ( vendorString ? dStrlen( vendorString ) : 0 )
  851. + ( rendererString ? dStrlen( rendererString ) : 0 )
  852. + ( versionString ? dStrlen( versionString ) : 0 )
  853. + ( extensionsString ? dStrlen( extensionsString ) : 0 )
  854. + 4;
  855. char* returnString = Con::getReturnBuffer( bufferLen );
  856. dSprintf( returnString, bufferLen, "%s\t%s\t%s\t%s",
  857. ( vendorString ? vendorString : "" ),
  858. ( rendererString ? rendererString : "" ),
  859. ( versionString ? versionString : "" ),
  860. ( extensionsString ? extensionsString : "" ) );
  861. return( returnString );
  862. }
  863. //------------------------------------------------------------------------------
  864. bool OpenGLDevice::getGammaCorrection(F32 &g)
  865. {
  866. U16 ramp[256*3];
  867. if (!GetDeviceGammaRamp(winState.appDC, ramp))
  868. return false;
  869. F32 csum = 0.0;
  870. U32 ccount = 0;
  871. for (U16 i = 0; i < 256; ++i)
  872. {
  873. if (i != 0 && ramp[i] != 0 && ramp[i] != 65535)
  874. {
  875. F64 b = (F64) i/256.0;
  876. F64 a = (F64) ramp[i]/65535.0;
  877. F32 c = (F32) (mLog(a)/mLog(b));
  878. csum += c;
  879. ++ccount;
  880. }
  881. }
  882. g = csum/ccount;
  883. return true;
  884. }
  885. //------------------------------------------------------------------------------
  886. bool OpenGLDevice::setGammaCorrection(F32 g)
  887. {
  888. U16 ramp[256*3];
  889. for (U16 i = 0; i < 256; ++i)
  890. ramp[i] = (U16)((U16)mPow((F32) i/256.0f, g) * 65535.0f);
  891. dMemcpy(&ramp[256],ramp,256*sizeof(U16));
  892. dMemcpy(&ramp[512],ramp,256*sizeof(U16));
  893. return SetDeviceGammaRamp(winState.appDC, ramp);
  894. }
  895. //------------------------------------------------------------------------------
  896. bool OpenGLDevice::setVerticalSync( bool on )
  897. {
  898. if ( !gGLState.suppSwapInterval )
  899. return( false );
  900. return( dwglSwapIntervalEXT( on ? 1 : 0 ) );
  901. }
  902. //------------------------------------------------------------------------------
  903. DisplayDevice* OpenGLDevice::create()
  904. {
  905. // Get Bit Depth Switching Info.
  906. enumerateBitDepths();
  907. bool result = false;
  908. bool fullScreenOnly = false;
  909. //------------------------------------------------------------------------------
  910. // This shouldn't happen, but just to be safe...
  911. //------------------------------------------------------------------------------
  912. if ( winState.hinstOpenGL )
  913. GL_Shutdown();
  914. //------------------------------------------------------------------------------
  915. // Initialize GL
  916. //------------------------------------------------------------------------------
  917. if (!GL_Init( "opengl32", "glu32" ))
  918. return NULL;
  919. //------------------------------------------------------------------------------
  920. // Create a test window to see if OpenGL hardware acceleration is available:
  921. //------------------------------------------------------------------------------
  922. WNDCLASS wc;
  923. dMemset(&wc, 0, sizeof(wc));
  924. wc.style = CS_OWNDC;
  925. wc.lpfnWndProc = DefWindowProc;
  926. wc.hInstance = winState.appInstance;
  927. wc.lpszClassName = dT("OGLTest");
  928. RegisterClass( &wc );
  929. //------------------------------------------------------------------------------
  930. // Create the Test Window
  931. //------------------------------------------------------------------------------
  932. //MIN_RESOLUTION defined in platformWin32/platformGL.h
  933. HWND testWindow = CreateWindow( dT("OGLTest"),dT(""), WS_POPUP, 0, 0, MIN_RESOLUTION_X, MIN_RESOLUTION_Y, NULL, NULL, winState.appInstance, NULL );
  934. if ( !testWindow )
  935. {
  936. // Unregister the Window Class
  937. UnregisterClass( dT("OGLTest"), winState.appInstance );
  938. // Shutdown GL
  939. GL_Shutdown();
  940. // Return Failure
  941. return NULL;
  942. }
  943. //------------------------------------------------------------------------------
  944. // Attempt to Grab a handle to the DeviceContext of our window.
  945. //------------------------------------------------------------------------------
  946. HDC testDC = GetDC( testWindow );
  947. if ( !testDC )
  948. {
  949. // Destroy the Window
  950. DestroyWindow( testWindow );
  951. // Unregister the Window Class
  952. UnregisterClass( dT("OGLTest"), winState.appInstance );
  953. // Shutdown GL
  954. GL_Shutdown();
  955. // Return Failure.
  956. return NULL;
  957. }
  958. //------------------------------------------------------------------------------
  959. // Create Pixel Format ( Default 16bpp )
  960. //------------------------------------------------------------------------------
  961. PIXELFORMATDESCRIPTOR pfd;
  962. CreatePixelFormat( &pfd, 16, 16, 8, false );
  963. U32 chosenFormat = ChooseBestPixelFormat( testDC, &pfd );
  964. if ( chosenFormat != 0 )
  965. {
  966. dwglDescribePixelFormat( testDC, chosenFormat, sizeof( pfd ), &pfd );
  967. result = !( pfd.dwFlags & PFD_GENERIC_FORMAT );
  968. if ( result && winState.desktopBitsPixel < 16 && !smCanDo32Bit)
  969. {
  970. // If Windows 95 cannot switch bit depth, it should only attempt 16-bit cards
  971. // with a 16-bit desktop
  972. // See if we can get a 32-bit pixel format:
  973. PIXELFORMATDESCRIPTOR pfd;
  974. CreatePixelFormat( &pfd, 32, 24, 8, false );
  975. S32 chosenFormat = ChooseBestPixelFormat( testDC, &pfd );
  976. if ( chosenFormat != 0 )
  977. {
  978. dwglDescribePixelFormat( winState.appDC, chosenFormat, sizeof( pfd ), &pfd );
  979. if (pfd.cColorBits == 16)
  980. {
  981. Platform::AlertOK("Requires 16-Bit Desktop",
  982. "You must run in 16-bit color to run a Torque game.\nPlease quit the game, set your desktop color depth to 16-bit\nand then restart the application.");
  983. result = false;
  984. }
  985. }
  986. }
  987. }
  988. else if ( winState.desktopBitsPixel < 16 && smCanSwitchBitDepth )
  989. {
  990. // Try again after changing the display to 16-bit:
  991. ReleaseDC( testWindow, testDC );
  992. DestroyWindow( testWindow );
  993. DEVMODE devMode;
  994. dMemset( &devMode, 0, sizeof( devMode ) );
  995. devMode.dmSize = sizeof( devMode );
  996. devMode.dmBitsPerPel = 16;
  997. devMode.dmFields = DM_BITSPERPEL;
  998. U32 test = ChangeDisplaySettings( &devMode, 0 );
  999. if ( test == DISP_CHANGE_SUCCESSFUL )
  1000. {
  1001. //MIN_RESOLUTION defined in platformWin32/platformGL.h
  1002. testWindow = CreateWindow( dT("OGLTest"), dT(""), WS_OVERLAPPED | WS_CAPTION, 0, 0, MIN_RESOLUTION_X, MIN_RESOLUTION_Y, NULL, NULL, winState.appInstance, NULL );
  1003. if ( testWindow )
  1004. {
  1005. testDC = GetDC( testWindow );
  1006. if ( testDC )
  1007. {
  1008. CreatePixelFormat( &pfd, 16, 16, 8, false );
  1009. chosenFormat = ChooseBestPixelFormat( testDC, &pfd );
  1010. if ( chosenFormat != 0 )
  1011. {
  1012. dwglDescribePixelFormat( testDC, chosenFormat, sizeof( pfd ), &pfd );
  1013. result = !( pfd.dwFlags & PFD_GENERIC_FORMAT );
  1014. if ( result )
  1015. fullScreenOnly = true;
  1016. }
  1017. }
  1018. }
  1019. }
  1020. ChangeDisplaySettings( NULL, 0 );
  1021. }
  1022. //------------------------------------------------------------------------------
  1023. // Can't do even 16 bit, alert user they need to upgrade.
  1024. //------------------------------------------------------------------------------
  1025. else if ( winState.desktopBitsPixel < 16 && !smCanSwitchBitDepth )
  1026. {
  1027. Platform::AlertOK("Requires 16-Bit Desktop", "You must run in 16-bit color to run a Torque game.\nPlease quit the game, set your desktop color depth to 16-bit\nand then restart the application.");
  1028. }
  1029. ReleaseDC( testWindow, testDC );
  1030. DestroyWindow( testWindow );
  1031. UnregisterClass( dT("OGLTest"), winState.appInstance );
  1032. GL_Shutdown();
  1033. if ( result )
  1034. {
  1035. OpenGLDevice* newOGLDevice = new OpenGLDevice();
  1036. if ( newOGLDevice )
  1037. {
  1038. newOGLDevice->mFullScreenOnly = fullScreenOnly;
  1039. return (DisplayDevice*) newOGLDevice;
  1040. }
  1041. else
  1042. return NULL;
  1043. }
  1044. else
  1045. return NULL;
  1046. }