winOGLVideo.cc 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841
  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. #include "winOGLVideo_ScriptBinding.h"
  33. //------------------------------------------------------------------------------
  34. OpenGLDevice::OpenGLDevice()
  35. {
  36. initDevice();
  37. }
  38. //------------------------------------------------------------------------------
  39. void OpenGLDevice::initDevice()
  40. {
  41. // Set the device name:
  42. mDeviceName = "OpenGL";
  43. // Let Parent enumerate valid resolutions.
  44. Parent::initDevice();
  45. }
  46. //------------------------------------------------------------------------------
  47. bool OpenGLDevice::activate( U32 width, U32 height, U32 bpp, bool fullScreen )
  48. {
  49. Con::printf( "Activating the OpenGL display device..." );
  50. bool needResurrect = false;
  51. // If the rendering context exists, delete it:
  52. if ( winState.hGLRC )
  53. {
  54. Con::printf( "Killing the texture manager..." );
  55. Game->textureKill();
  56. needResurrect = true;
  57. Con::printf( "Making the rendering context not current..." );
  58. if ( !dwglMakeCurrent( NULL, NULL ) )
  59. {
  60. AssertFatal( false, "OpenGLDevice::activate\ndwglMakeCurrent( NULL, NULL ) failed!" );
  61. return false;
  62. }
  63. Con::printf( "Deleting the rendering context ..." );
  64. if ( !dwglDeleteContext( winState.hGLRC ) )
  65. {
  66. AssertFatal( false, "OpenGLDevice::activate\ndwglDeleteContext failed!" );
  67. return false;
  68. }
  69. winState.hGLRC = NULL;
  70. }
  71. // [neo, 5/31/2007 - #3174]
  72. if( winState.appMenu )
  73. {
  74. DestroyMenu( winState.appMenu );
  75. winState.appMenu = NULL;
  76. }
  77. // If the window already exists, kill it so we can start fresh:
  78. if ( winState.appWindow )
  79. {
  80. if ( winState.appDC )
  81. {
  82. Con::printf( "Releasing the device context..." );
  83. ReleaseDC( winState.appWindow, winState.appDC );
  84. winState.appDC = NULL;
  85. }
  86. Con::printf( "Destroying the window..." );
  87. DestroyWindow( winState.appWindow );
  88. winState.appWindow = NULL;
  89. }
  90. // If OpenGL library already loaded, shut it down and reload it:
  91. if ( winState.hinstOpenGL )
  92. GL_Shutdown();
  93. GL_Init( "opengl32", "glu32" );
  94. // Set the resolution:
  95. if ( !setScreenMode( width, height, bpp, ( fullScreen || mFullScreenOnly ), true, false ) )
  96. return false;
  97. // Get original gamma ramp
  98. mRestoreGamma = GetDeviceGammaRamp(winState.appDC, mOriginalRamp);
  99. // Output some driver info to the console:
  100. const char* vendorString = (const char*) glGetString( GL_VENDOR );
  101. const char* rendererString = (const char*) glGetString( GL_RENDERER );
  102. const char* versionString = (const char*) glGetString( GL_VERSION );
  103. Con::printf( "OpenGL driver information:" );
  104. if ( vendorString )
  105. Con::printf( " Vendor: %s", vendorString );
  106. if ( rendererString )
  107. Con::printf( " Renderer: %s", rendererString );
  108. if ( versionString )
  109. Con::printf( " Version: %s", versionString );
  110. if ( needResurrect )
  111. {
  112. // Reload the textures:
  113. Con::printf( "Resurrecting the texture manager..." );
  114. Game->textureResurrect();
  115. }
  116. GL_EXT_Init();
  117. Con::setVariable( "$pref::Video::displayDevice", mDeviceName );
  118. // Do this here because we now know about the extensions:
  119. if ( gGLState.suppSwapInterval )
  120. setVerticalSync( !Con::getBoolVariable( "$pref::Video::disableVerticalSync" ) );
  121. return true;
  122. }
  123. //------------------------------------------------------------------------------
  124. void OpenGLDevice::shutdown()
  125. {
  126. Con::printf( "Shutting down the OpenGL display device..." );
  127. if ( winState.hGLRC )
  128. {
  129. if (mRestoreGamma)
  130. SetDeviceGammaRamp(winState.appDC, mOriginalRamp);
  131. Con::printf( "Making the GL rendering context not current..." );
  132. dwglMakeCurrent( NULL, NULL );
  133. if ( Con::getBoolVariable("$pref::Video::deleteContext", true) )
  134. {
  135. Con::printf( "Deleting the GL rendering context..." );
  136. dwglDeleteContext( winState.hGLRC );
  137. }
  138. winState.hGLRC = NULL;
  139. }
  140. if ( winState.appDC )
  141. {
  142. Con::printf( "Releasing the device context..." );
  143. ReleaseDC( winState.appWindow, winState.appDC );
  144. winState.appDC = NULL;
  145. }
  146. if ( smIsFullScreen )
  147. {
  148. Con::printf( "Restoring the desktop display settings (%dx%dx%d)...", winState.desktopWidth, winState.desktopHeight, winState.desktopBitsPixel );
  149. ChangeDisplaySettings( NULL, 0 );
  150. }
  151. }
  152. //------------------------------------------------------------------------------
  153. // This is the real workhorse function of the DisplayDevice...
  154. //
  155. bool OpenGLDevice::setScreenMode( U32 width, U32 height, U32 bpp, bool fullScreen, bool forceIt, bool repaint )
  156. {
  157. HWND curtain = NULL;
  158. char errorMessage[256];
  159. Resolution newRes( width, height, bpp );
  160. bool newFullScreen = fullScreen;
  161. bool safeModeOn = Con::getBoolVariable( "$pref::Video::safeModeOn" );
  162. if ( !newFullScreen && mFullScreenOnly )
  163. {
  164. Con::warnf( ConsoleLogEntry::General, "OpenGLDevice::setScreenMode - device or desktop color depth does not allow windowed mode!" );
  165. newFullScreen = true;
  166. }
  167. if ( !newFullScreen && ( (S32)newRes.w >= winState.desktopClientWidth || (S32)newRes.h >= winState.desktopClientHeight ) )
  168. {
  169. Con::warnf( ConsoleLogEntry::General, "OpenGLDevice::setScreenMode -- can't switch to resolution larger than desktop in windowed mode!" );
  170. S32 resIndex = 0;
  171. S32 bestScore = 0, thisScore = 0;
  172. for ( S32 i = 0; i < mResolutionList.size(); i++ )
  173. {
  174. if ( newRes == mResolutionList[i] )
  175. {
  176. resIndex = i;
  177. break;
  178. }
  179. else if( (S32)newRes.h <= winState.desktopClientHeight && (S32)newRes.w <= winState.desktopClientWidth )
  180. {
  181. thisScore = abs( S32( newRes.w ) - S32( mResolutionList[i].w ) )
  182. + abs( S32( newRes.h ) - S32( mResolutionList[i].h ) )
  183. + ( newRes.bpp == mResolutionList[i].bpp ? 0 : 1 );
  184. if ( !bestScore || ( thisScore < bestScore ) )
  185. {
  186. bestScore = thisScore;
  187. resIndex = i;
  188. }
  189. }
  190. }
  191. }
  192. //MIN_RESOLUTION defined in platformWin32/platformGL.h
  193. if ( newRes.w < MIN_RESOLUTION_X || newRes.h < MIN_RESOLUTION_Y )
  194. {
  195. Con::warnf( ConsoleLogEntry::General, "OpenGLDevice::setScreenMode -- can't go smaller than 640x480!" );
  196. return false;
  197. }
  198. if ( newFullScreen )
  199. {
  200. if (newRes.bpp != 16 && mFullScreenOnly)
  201. newRes.bpp = 16;
  202. // Match the new resolution to one in the list:
  203. U32 resIndex = 0;
  204. U32 bestScore = 0, thisScore = 0;
  205. for ( int i = 0; i < mResolutionList.size(); i++ )
  206. {
  207. if ( newRes == mResolutionList[i] )
  208. {
  209. resIndex = i;
  210. break;
  211. }
  212. else
  213. {
  214. thisScore = abs( S32( newRes.w ) - S32( mResolutionList[i].w ) )
  215. + abs( S32( newRes.h ) - S32( mResolutionList[i].h ) )
  216. + ( newRes.bpp == mResolutionList[i].bpp ? 0 : 1 );
  217. if ( !bestScore || ( thisScore < bestScore ) )
  218. {
  219. bestScore = thisScore;
  220. resIndex = i;
  221. }
  222. }
  223. }
  224. newRes = mResolutionList[resIndex];
  225. }
  226. else
  227. {
  228. // Basically ignore the bit depth parameter:
  229. newRes.bpp = winState.desktopBitsPixel;
  230. }
  231. // Return if already at this resolution:
  232. if ( !forceIt && newRes == smCurrentRes && newFullScreen == smIsFullScreen )
  233. return true;
  234. Con::printf( "Setting screen mode to %dx%dx%d (%s)...", newRes.w, newRes.h, newRes.bpp, ( newFullScreen ? "fs" : "w" ) );
  235. bool needResurrect = false;
  236. if ( ( newRes.bpp != smCurrentRes.bpp ) || ( safeModeOn && ( ( smIsFullScreen != newFullScreen ) || newFullScreen ) ) )
  237. {
  238. // Delete the rendering context:
  239. if ( winState.hGLRC )
  240. {
  241. if (!Video::smNeedResurrect)
  242. {
  243. Con::printf( "Killing the texture manager..." );
  244. Game->textureKill();
  245. needResurrect = true;
  246. }
  247. Con::printf( "Making the rendering context not current..." );
  248. if ( !dwglMakeCurrent( NULL, NULL ) )
  249. {
  250. AssertFatal( false, "OpenGLDevice::setScreenMode\ndwglMakeCurrent( NULL, NULL ) failed!" );
  251. return false;
  252. }
  253. Con::printf( "Deleting the rendering context..." );
  254. if ( Con::getBoolVariable("$pref::Video::deleteContext",true) &&
  255. !dwglDeleteContext( winState.hGLRC ) )
  256. {
  257. AssertFatal( false, "OpenGLDevice::setScreenMode\ndwglDeleteContext failed!" );
  258. return false;
  259. }
  260. winState.hGLRC = NULL;
  261. }
  262. // Release the device context:
  263. if ( winState.appDC )
  264. {
  265. Con::printf( "Releasing the device context..." );
  266. ReleaseDC( winState.appWindow, winState.appDC );
  267. winState.appDC = NULL;
  268. }
  269. // [neo, 5/31/2007 - #3174]
  270. if( winState.appMenu )
  271. {
  272. DestroyMenu( winState.appMenu );
  273. winState.appMenu = NULL;
  274. }
  275. // Destroy the window:
  276. if ( winState.appWindow )
  277. {
  278. Con::printf( "Destroying the window..." );
  279. DestroyWindow( winState.appWindow );
  280. winState.appWindow = NULL;
  281. }
  282. }
  283. else if ( smIsFullScreen != newFullScreen )
  284. {
  285. // Change the window style:
  286. Con::printf( "Changing the window style..." );
  287. S32 windowStyle = WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
  288. if ( newFullScreen )
  289. windowStyle |= ( WS_MAXIMIZE | WS_VISIBLE);
  290. else
  291. windowStyle |= ( WS_OVERLAPPEDWINDOW );
  292. if ( winState.appWindow && !SetWindowLong( winState.appWindow, GWL_STYLE, windowStyle ) )
  293. Con::errorf( "SetWindowLong failed to change the window style!" );
  294. }
  295. if( winState.appWindow && !newFullScreen )
  296. ShowWindow( winState.appWindow, SW_NORMAL );
  297. else
  298. ShowWindow( winState.appWindow, SW_MAXIMIZE );
  299. U32 test;
  300. if ( newFullScreen )
  301. {
  302. // Change the display settings:
  303. DEVMODE devMode;
  304. dMemset( &devMode, 0, sizeof( devMode ) );
  305. devMode.dmSize = sizeof( devMode );
  306. devMode.dmPelsWidth = newRes.w;
  307. devMode.dmPelsHeight = newRes.h;
  308. devMode.dmBitsPerPel = newRes.bpp;
  309. devMode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
  310. Con::printf( "Changing the display settings to %dx%dx%d...", newRes.w, newRes.h, newRes.bpp );
  311. curtain = CreateCurtain( newRes.w, newRes.h );
  312. test = ChangeDisplaySettings( &devMode, CDS_FULLSCREEN );
  313. if ( test != DISP_CHANGE_SUCCESSFUL )
  314. {
  315. smIsFullScreen = false;
  316. Con::setBoolVariable( "$pref::Video::fullScreen", false );
  317. ChangeDisplaySettings( NULL, 0 );
  318. Con::errorf( ConsoleLogEntry::General, "OpenGLDevice::setScreenMode - ChangeDisplaySettings failed." );
  319. switch( test )
  320. {
  321. case DISP_CHANGE_RESTART:
  322. Platform::AlertOK( "Display Change Failed", "You must restart your machine to get the specified mode." );
  323. break;
  324. case DISP_CHANGE_BADMODE:
  325. Platform::AlertOK( "Display Change Failed", "The specified mode is not supported by this device." );
  326. break;
  327. default:
  328. Platform::AlertOK( "Display Change Failed", "Hardware failed to switch to the specified mode." );
  329. break;
  330. };
  331. DestroyWindow( curtain );
  332. return false;
  333. }
  334. else
  335. smIsFullScreen = true;
  336. }
  337. else if ( smIsFullScreen )
  338. {
  339. Con::printf( "Changing to the desktop display settings (%dx%dx%d)...", winState.desktopWidth, winState.desktopHeight, winState.desktopBitsPixel );
  340. ChangeDisplaySettings( NULL, 0 );
  341. smIsFullScreen = false;
  342. }
  343. Con::setBoolVariable( "$pref::Video::fullScreen", smIsFullScreen );
  344. bool newWindow = false;
  345. if ( !winState.appWindow )
  346. {
  347. Con::printf( "Creating a new %swindow...", ( fullScreen ? "full-screen " : "" ) );
  348. winState.appWindow = CreateOpenGLWindow( newRes.w, newRes.h, newFullScreen, true );
  349. if ( !winState.appWindow )
  350. {
  351. AssertFatal( false, "OpenGLDevice::setScreenMode\nFailed to create a new window!" );
  352. return false;
  353. }
  354. newWindow = true;
  355. }
  356. // Move the window:
  357. if ( !newFullScreen )
  358. {
  359. // Adjust the window rect to compensate for the window style:
  360. RECT windowRect;
  361. windowRect.left = windowRect.top = 0;
  362. windowRect.right = newRes.w;
  363. windowRect.bottom = newRes.h;
  364. AdjustWindowRect( &windowRect, GetWindowLong( winState.appWindow, GWL_STYLE ), false );
  365. U32 adjWidth = windowRect.right - windowRect.left;
  366. U32 adjHeight = windowRect.bottom - windowRect.top;
  367. // Center the window on the desktop:
  368. U32 xPos = 0, yPos = 0;
  369. if(adjWidth < (U32)winState.desktopClientWidth)
  370. xPos = ( winState.desktopClientWidth - adjWidth ) / 2;
  371. if(adjHeight < (U32)winState.desktopClientHeight)
  372. yPos = ( winState.desktopClientHeight - adjHeight ) / 2;
  373. test = SetWindowPos( winState.appWindow, 0, xPos, yPos, adjWidth, adjHeight, SWP_NOZORDER );
  374. if ( !test )
  375. {
  376. 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 );
  377. AssertFatal( false, errorMessage );
  378. return false;
  379. }
  380. AnimateWindow( winState.appWindow, 90, AW_BLEND );
  381. }
  382. else if ( !newWindow )
  383. {
  384. // Move and size the window to take up the whole screen:
  385. if ( !SetWindowPos( winState.appWindow, HWND_TOPMOST, 0, 0, newRes.w, newRes.h, SWP_NOACTIVATE)
  386. || !SetWindowPos( winState.appWindow, HWND_TOPMOST, 0, 0, newRes.w, newRes.h, SWP_NOZORDER) )
  387. {
  388. dSprintf( errorMessage, 255, "OpenGLDevice::setScreenMode\nSetWindowPos failed to move the window to (0,0) and size it to %dx%d.", newRes.w, newRes.h );
  389. AssertFatal( false, errorMessage );
  390. return false;
  391. }
  392. }
  393. bool newDeviceContext = false;
  394. if ( !winState.appDC )
  395. {
  396. // Get a new device context:
  397. Con::printf( "Acquiring a new device context..." );
  398. winState.appDC = GetDC( winState.appWindow );
  399. if ( !winState.appDC )
  400. {
  401. AssertFatal( false, "OpenGLDevice::setScreenMode\nGetDC failed to get a valid device context!" );
  402. return false;
  403. }
  404. newDeviceContext = true;
  405. }
  406. if ( newWindow )
  407. {
  408. // Set the pixel format of the new window:
  409. PIXELFORMATDESCRIPTOR pfd;
  410. CreatePixelFormat( &pfd, newRes.bpp, 24, 8, false );
  411. S32 chosenFormat = ChooseBestPixelFormat( winState.appDC, &pfd );
  412. if ( !chosenFormat )
  413. {
  414. AssertFatal( false, "OpenGLDevice::setScreenMode\nNo valid pixel formats found!" );
  415. return false;
  416. }
  417. dwglDescribePixelFormat( winState.appDC, chosenFormat, sizeof( pfd ), &pfd );
  418. if ( !SetPixelFormat( winState.appDC, chosenFormat, &pfd ) )
  419. {
  420. AssertFatal( false, "OpenGLDevice::setScreenMode\nFailed to set the pixel format!" );
  421. return false;
  422. }
  423. Con::printf( "Pixel format set:" );
  424. Con::printf( " %d color bits, %d depth bits, %d stencil bits", pfd.cColorBits, pfd.cDepthBits, pfd.cStencilBits );
  425. }
  426. if ( !winState.hGLRC )
  427. {
  428. // Create a new rendering context:
  429. Con::printf( "Creating a new rendering context..." );
  430. winState.hGLRC = dwglCreateContext( winState.appDC );
  431. if ( !winState.hGLRC )
  432. {
  433. AssertFatal( false, "OpenGLDevice::setScreenMode\ndwglCreateContext failed to create an OpenGL rendering context!" );
  434. return false;
  435. }
  436. // Make the new rendering context current:
  437. Con::printf( "Making the new rendering context current..." );
  438. if ( !dwglMakeCurrent( winState.appDC, winState.hGLRC ) )
  439. {
  440. AssertFatal( false, "OpenGLDevice::setScreenMode\ndwglMakeCurrent failed to make the rendering context current!" );
  441. return false;
  442. }
  443. // Just for kicks. Seems a relatively central place to put this...
  444. glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  445. if ( needResurrect )
  446. {
  447. // Reload the textures:
  448. Con::printf( "Resurrecting the texture manager..." );
  449. Game->textureResurrect();
  450. }
  451. }
  452. // Just for kicks. Seems a relatively central place to put this...
  453. glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  454. if ( newDeviceContext && gGLState.suppSwapInterval )
  455. setVerticalSync( !Con::getBoolVariable( "$pref::Video::disableVerticalSync" ) );
  456. smCurrentRes = newRes;
  457. Platform::setWindowSize( newRes.w, newRes.h );
  458. char tempBuf[15];
  459. dSprintf( tempBuf, sizeof( tempBuf ), "%d %d %d", smCurrentRes.w, smCurrentRes.h, smCurrentRes.bpp );
  460. if( fullScreen )
  461. Con::setVariable( "$pref::Video::resolution", tempBuf );
  462. else
  463. Con::setVariable( "$pref::Video::windowedRes", tempBuf );
  464. if ( curtain )
  465. DestroyWindow( curtain );
  466. // Doesn't hurt to do this even it isn't necessary:
  467. ShowWindow( winState.appWindow, SW_SHOW );
  468. SetForegroundWindow( winState.appWindow );
  469. SetFocus( winState.appWindow );
  470. if (newFullScreen)
  471. {
  472. // Doesn't hurt to do this an extra time, and seems to help in some cases
  473. if ( !SetWindowPos( winState.appWindow, HWND_TOPMOST, 0, 0, newRes.w, newRes.h, SWP_NOACTIVATE)
  474. || !SetWindowPos( winState.appWindow, HWND_TOPMOST, 0, 0, newRes.w, newRes.h, SWP_NOZORDER) )
  475. {
  476. dSprintf( errorMessage, 255, "OpenGLDevice::setScreenMode\nSetWindowPos failed to move the window to (0,0) and size it to %dx%d.", newRes.w, newRes.h );
  477. AssertFatal( false, errorMessage );
  478. return false;
  479. }
  480. }
  481. //Luma: Clear window at first, as it is showing previous gl color buffer stuff.
  482. glClearColor(0.0f,0.0f,0.0f,0.0f);
  483. glClear(GL_COLOR_BUFFER_BIT);
  484. if ( repaint )
  485. Video::resetCanvas();
  486. return true;
  487. }
  488. //------------------------------------------------------------------------------
  489. void OpenGLDevice::swapBuffers()
  490. {
  491. dwglSwapBuffers( winState.appDC );
  492. }
  493. //------------------------------------------------------------------------------
  494. const char* OpenGLDevice::getDriverInfo()
  495. {
  496. // Output some driver info to the console:
  497. const char* vendorString = (const char*) glGetString( GL_VENDOR );
  498. const char* rendererString = (const char*) glGetString( GL_RENDERER );
  499. const char* versionString = (const char*) glGetString( GL_VERSION );
  500. const char* extensionsString = (const char*) glGetString( GL_EXTENSIONS );
  501. U32 bufferLen = ( vendorString ? dStrlen( vendorString ) : 0 )
  502. + ( rendererString ? dStrlen( rendererString ) : 0 )
  503. + ( versionString ? dStrlen( versionString ) : 0 )
  504. + ( extensionsString ? dStrlen( extensionsString ) : 0 )
  505. + 4;
  506. char* returnString = Con::getReturnBuffer( bufferLen );
  507. dSprintf( returnString, bufferLen, "%s\t%s\t%s\t%s",
  508. ( vendorString ? vendorString : "" ),
  509. ( rendererString ? rendererString : "" ),
  510. ( versionString ? versionString : "" ),
  511. ( extensionsString ? extensionsString : "" ) );
  512. return( returnString );
  513. }
  514. //------------------------------------------------------------------------------
  515. bool OpenGLDevice::getGammaCorrection(F32 &g)
  516. {
  517. U16 ramp[256*3];
  518. if (!GetDeviceGammaRamp(winState.appDC, ramp))
  519. return false;
  520. F32 csum = 0.0;
  521. U32 ccount = 0;
  522. for (U16 i = 0; i < 256; ++i)
  523. {
  524. if (i != 0 && ramp[i] != 0 && ramp[i] != 65535)
  525. {
  526. F64 b = (F64) i/256.0;
  527. F64 a = (F64) ramp[i]/65535.0;
  528. F32 c = (F32) (mLog(a)/mLog(b));
  529. csum += c;
  530. ++ccount;
  531. }
  532. }
  533. g = csum/ccount;
  534. return true;
  535. }
  536. //------------------------------------------------------------------------------
  537. bool OpenGLDevice::setGammaCorrection(F32 g)
  538. {
  539. U16 ramp[256*3];
  540. for (U16 i = 0; i < 256; ++i)
  541. ramp[i] = (U16)((U16)mPow((F32) i/256.0f, g) * 65535.0f);
  542. dMemcpy(&ramp[256],ramp,256*sizeof(U16));
  543. dMemcpy(&ramp[512],ramp,256*sizeof(U16));
  544. return SetDeviceGammaRamp(winState.appDC, ramp);
  545. }
  546. //------------------------------------------------------------------------------
  547. bool OpenGLDevice::getVerticalSync()
  548. {
  549. if ( !gGLState.suppSwapInterval )
  550. return( false );
  551. //Note that dwglGetSwapIntervalEXT returns the number of frames between Swaps.
  552. //The function returns 0 / false if SwapInterval has not been specified.
  553. return (dwglGetSwapIntervalEXT());
  554. }
  555. //------------------------------------------------------------------------------
  556. bool OpenGLDevice::setVerticalSync( bool on )
  557. {
  558. if ( !gGLState.suppSwapInterval )
  559. return( false );
  560. return( dwglSwapIntervalEXT( on ? 1 : 0 ) );
  561. }
  562. //------------------------------------------------------------------------------
  563. DisplayDevice* OpenGLDevice::create()
  564. {
  565. // Get Bit Depth Switching Info.
  566. enumerateBitDepths();
  567. bool result = false;
  568. bool fullScreenOnly = false;
  569. //------------------------------------------------------------------------------
  570. // This shouldn't happen, but just to be safe...
  571. //------------------------------------------------------------------------------
  572. if ( winState.hinstOpenGL )
  573. GL_Shutdown();
  574. //------------------------------------------------------------------------------
  575. // Initialize GL
  576. //------------------------------------------------------------------------------
  577. if (!GL_Init( "opengl32", "glu32" ))
  578. return NULL;
  579. //------------------------------------------------------------------------------
  580. // Create a test window to see if OpenGL hardware acceleration is available:
  581. //------------------------------------------------------------------------------
  582. WNDCLASS wc;
  583. dMemset(&wc, 0, sizeof(wc));
  584. wc.style = CS_OWNDC;
  585. wc.lpfnWndProc = DefWindowProc;
  586. wc.hInstance = winState.appInstance;
  587. wc.lpszClassName = dT("OGLTest");
  588. RegisterClass( &wc );
  589. //------------------------------------------------------------------------------
  590. // Create the Test Window
  591. //------------------------------------------------------------------------------
  592. //MIN_RESOLUTION defined in platformWin32/platformGL.h
  593. HWND testWindow = CreateWindow( dT("OGLTest"),dT(""), WS_POPUP, 0, 0, MIN_RESOLUTION_X, MIN_RESOLUTION_Y, NULL, NULL, winState.appInstance, NULL );
  594. if ( !testWindow )
  595. {
  596. // Unregister the Window Class
  597. UnregisterClass( dT("OGLTest"), winState.appInstance );
  598. // Shutdown GL
  599. GL_Shutdown();
  600. // Return Failure
  601. return NULL;
  602. }
  603. //------------------------------------------------------------------------------
  604. // Attempt to Grab a handle to the DeviceContext of our window.
  605. //------------------------------------------------------------------------------
  606. HDC testDC = GetDC( testWindow );
  607. if ( !testDC )
  608. {
  609. // Destroy the Window
  610. DestroyWindow( testWindow );
  611. // Unregister the Window Class
  612. UnregisterClass( dT("OGLTest"), winState.appInstance );
  613. // Shutdown GL
  614. GL_Shutdown();
  615. // Return Failure.
  616. return NULL;
  617. }
  618. //------------------------------------------------------------------------------
  619. // Create Pixel Format ( Default 16bpp )
  620. //------------------------------------------------------------------------------
  621. PIXELFORMATDESCRIPTOR pfd;
  622. CreatePixelFormat( &pfd, 16, 16, 8, false );
  623. U32 chosenFormat = ChooseBestPixelFormat( testDC, &pfd );
  624. if ( chosenFormat != 0 )
  625. {
  626. dwglDescribePixelFormat( testDC, chosenFormat, sizeof( pfd ), &pfd );
  627. result = !( pfd.dwFlags & PFD_GENERIC_FORMAT );
  628. if ( result && winState.desktopBitsPixel < 16 && !smCanDo32Bit)
  629. {
  630. // If Windows 95 cannot switch bit depth, it should only attempt 16-bit cards
  631. // with a 16-bit desktop
  632. // See if we can get a 32-bit pixel format:
  633. PIXELFORMATDESCRIPTOR pfd;
  634. CreatePixelFormat( &pfd, 32, 24, 8, false );
  635. S32 chosenFormat = ChooseBestPixelFormat( testDC, &pfd );
  636. if ( chosenFormat != 0 )
  637. {
  638. dwglDescribePixelFormat( winState.appDC, chosenFormat, sizeof( pfd ), &pfd );
  639. if (pfd.cColorBits == 16)
  640. {
  641. Platform::AlertOK("Requires 16-Bit Desktop",
  642. "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.");
  643. result = false;
  644. }
  645. }
  646. }
  647. }
  648. else if ( winState.desktopBitsPixel < 16 && smCanSwitchBitDepth )
  649. {
  650. // Try again after changing the display to 16-bit:
  651. ReleaseDC( testWindow, testDC );
  652. DestroyWindow( testWindow );
  653. DEVMODE devMode;
  654. dMemset( &devMode, 0, sizeof( devMode ) );
  655. devMode.dmSize = sizeof( devMode );
  656. devMode.dmBitsPerPel = 16;
  657. devMode.dmFields = DM_BITSPERPEL;
  658. U32 test = ChangeDisplaySettings( &devMode, 0 );
  659. if ( test == DISP_CHANGE_SUCCESSFUL )
  660. {
  661. //MIN_RESOLUTION defined in platformWin32/platformGL.h
  662. testWindow = CreateWindow( dT("OGLTest"), dT(""), WS_OVERLAPPED | WS_CAPTION, 0, 0, MIN_RESOLUTION_X, MIN_RESOLUTION_Y, NULL, NULL, winState.appInstance, NULL );
  663. if ( testWindow )
  664. {
  665. testDC = GetDC( testWindow );
  666. if ( testDC )
  667. {
  668. CreatePixelFormat( &pfd, 16, 16, 8, false );
  669. chosenFormat = ChooseBestPixelFormat( testDC, &pfd );
  670. if ( chosenFormat != 0 )
  671. {
  672. dwglDescribePixelFormat( testDC, chosenFormat, sizeof( pfd ), &pfd );
  673. result = !( pfd.dwFlags & PFD_GENERIC_FORMAT );
  674. if ( result )
  675. fullScreenOnly = true;
  676. }
  677. }
  678. }
  679. }
  680. ChangeDisplaySettings( NULL, 0 );
  681. }
  682. //------------------------------------------------------------------------------
  683. // Can't do even 16 bit, alert user they need to upgrade.
  684. //------------------------------------------------------------------------------
  685. else if ( winState.desktopBitsPixel < 16 && !smCanSwitchBitDepth )
  686. {
  687. 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.");
  688. }
  689. ReleaseDC( testWindow, testDC );
  690. DestroyWindow( testWindow );
  691. UnregisterClass( dT("OGLTest"), winState.appInstance );
  692. GL_Shutdown();
  693. if ( result )
  694. {
  695. OpenGLDevice* newOGLDevice = new OpenGLDevice();
  696. if ( newOGLDevice )
  697. {
  698. newOGLDevice->mFullScreenOnly = fullScreenOnly;
  699. return (DisplayDevice*) newOGLDevice;
  700. }
  701. else
  702. return NULL;
  703. }
  704. else
  705. return NULL;
  706. }