x86UNIXOGLVideo.client.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 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. #if 0
  23. #include "console/console.h"
  24. #include "platform/event.h"
  25. #include "platform/gameInterface.h"
  26. #include "platformX86UNIX/platformX86UNIX.h"
  27. #include "platformX86UNIX/platformGL.h"
  28. #include "platformX86UNIX/x86UNIXOGLVideo.h"
  29. #include "platformX86UNIX/x86UNIXState.h"
  30. #include <SDL/SDL.h>
  31. #include <SDL/SDL_syswm.h>
  32. #include <SDL/SDL_version.h>
  33. //------------------------------------------------------------------------------
  34. bool InitOpenGL()
  35. {
  36. DisplayDevice::init();
  37. // Get the video settings from the prefs:
  38. const char* resString = Con::getVariable( "$pref::Video::resolution" );
  39. dsize_t tempBufLen = dStrlen(resString) + 1;
  40. char* tempBuf = new char[tempBufLen];
  41. dStrcpy( tempBuf, resString, tempBufLen );
  42. char* temp = dStrtok( tempBuf, " x\0" );
  43. U32 width = ( temp ? dAtoi( temp ) : 800 );
  44. temp = dStrtok( NULL, " x\0" );
  45. U32 height = ( temp ? dAtoi( temp ) : 600 );
  46. temp = dStrtok( NULL, "\0" );
  47. U32 bpp = ( temp ? dAtoi( temp ) : 16 );
  48. delete [] tempBuf;
  49. bool fullScreen = Con::getBoolVariable( "$pref::Video::fullScreen" );
  50. // the only supported video device in unix is OpenGL
  51. if ( !Video::setDevice( "OpenGL", width, height, bpp, fullScreen ) )
  52. {
  53. Con::errorf("Unable to create default OpenGL mode: %d %d %d %d",
  54. width, height, bpp, fullScreen);
  55. // if we can't create the default, attempt to create a "safe" window
  56. if ( !Video::setDevice( "OpenGL", 640, 480, 16, true ) )
  57. {
  58. DisplayErrorAlert("Could not find a compatible OpenGL display " \
  59. "resolution. Please check your driver configuration.");
  60. return false;
  61. }
  62. }
  63. return true;
  64. }
  65. //------------------------------------------------------------------------------
  66. bool OpenGLDevice::smCanSwitchBitDepth = false;
  67. //------------------------------------------------------------------------------
  68. OpenGLDevice::OpenGLDevice()
  69. {
  70. initDevice();
  71. }
  72. //------------------------------------------------------------------------------
  73. OpenGLDevice::~OpenGLDevice()
  74. {
  75. }
  76. //------------------------------------------------------------------------------
  77. void OpenGLDevice::addResolution(S32 width, S32 height, bool check)
  78. {
  79. Point2I desktopSize = x86UNIXState->getDesktopSize();
  80. U32 desktopBpp = x86UNIXState->getDesktopBpp();
  81. // don't allow any resolution under this size
  82. if (width < 640 || height < 480)
  83. return;
  84. if (check)
  85. {
  86. // don't allow resolutions that exceed the current desktop size
  87. if (width > desktopSize.x || height > desktopSize.y)
  88. return;
  89. }
  90. if (smCanSwitchBitDepth)
  91. {
  92. // add both 16 and 32 bit resolutions
  93. mResolutionList.push_back(Resolution(width, height, 16));
  94. mResolutionList.push_back(Resolution(width, height, 32));
  95. }
  96. else
  97. {
  98. // add just the desktop resolution
  99. mResolutionList.push_back(Resolution(width, height, desktopBpp));
  100. }
  101. }
  102. //------------------------------------------------------------------------------
  103. void OpenGLDevice::initDevice()
  104. {
  105. mDeviceName = "OpenGL";
  106. mFullScreenOnly = false;
  107. }
  108. //------------------------------------------------------------------------------
  109. void OpenGLDevice::loadResolutions()
  110. {
  111. mResolutionList.clear();
  112. // X cannot switch bit depths on the fly. In case this feature is
  113. // implemented someday, calling this function will let you take
  114. // advantage of it
  115. if (Con::getBoolVariable("$pref::Unix::CanSwitchBitDepth"))
  116. smCanSwitchBitDepth = true;
  117. // add some default resolutions
  118. addResolution(640, 480);
  119. addResolution(800, 600);
  120. addResolution(1024, 768);
  121. addResolution(1152, 864);
  122. addResolution(1280, 1024);
  123. addResolution(1600, 1200);
  124. // specifying full screen should give us the resolutions that the
  125. // X server allows
  126. SDL_Rect** modes = SDL_ListModes(NULL, SDL_FULLSCREEN);
  127. if (modes &&
  128. (modes != (SDL_Rect **)-1))
  129. {
  130. for (int i = 0; modes[i] != NULL; ++i)
  131. {
  132. // do we already have this mode?
  133. bool found = false;
  134. for (Vector<Resolution>::iterator iter = mResolutionList.begin();
  135. iter != mResolutionList.end();
  136. ++iter)
  137. {
  138. if (iter->w == modes[i]->w && iter->h == modes[i]->h)
  139. {
  140. found = true;
  141. break;
  142. }
  143. }
  144. if (!found)
  145. // don't check these resolutions because they should be OK
  146. // (and checking might drop resolutions that are higher than the
  147. // current desktop bpp)
  148. addResolution(modes[i]->w, modes[i]->h, false);
  149. }
  150. }
  151. }
  152. //------------------------------------------------------------------------------
  153. bool OpenGLDevice::activate( U32 width, U32 height, U32 bpp, bool fullScreen )
  154. {
  155. if (!setScreenMode(width, height, bpp, fullScreen))
  156. {
  157. Con::printf("Unable to set screen mode.");
  158. return false;
  159. }
  160. // Output some driver info to the console
  161. const char* vendorString = (const char*) glGetString( GL_VENDOR );
  162. const char* rendererString = (const char*) glGetString( GL_RENDERER );
  163. const char* versionString = (const char*) glGetString( GL_VERSION );
  164. Con::printf( "OpenGL driver information:" );
  165. if ( vendorString )
  166. Con::printf( " Vendor: %s", vendorString );
  167. if ( rendererString )
  168. Con::printf( " Renderer: %s", rendererString );
  169. if ( versionString )
  170. Con::printf( " Version: %s", versionString );
  171. GL_EXT_Init();
  172. Con::setVariable( "$pref::Video::displayDevice", mDeviceName );
  173. // Do this here because we now know about the extensions:
  174. if ( gGLState.suppSwapInterval )
  175. setVerticalSync(
  176. !Con::getBoolVariable( "$pref::Video::disableVerticalSync" ) );
  177. Con::setBoolVariable("$pref::OpenGL::allowTexGen", true);
  178. return true;
  179. }
  180. //------------------------------------------------------------------------------
  181. void OpenGLDevice::shutdown()
  182. {
  183. // Shutdown is deferred to Platform::shutdown()
  184. }
  185. //------------------------------------------------------------------------------
  186. static void PrintGLAttributes()
  187. {
  188. int doubleBuf;
  189. int bufferSize, depthSize, stencilSize;
  190. int red, green, blue, alpha;
  191. int aRed, aGreen, aBlue, aAlpha;
  192. SDL_GL_GetAttribute(SDL_GL_DOUBLEBUFFER, &doubleBuf);
  193. SDL_GL_GetAttribute(SDL_GL_BUFFER_SIZE, &bufferSize);
  194. SDL_GL_GetAttribute(SDL_GL_DEPTH_SIZE, &depthSize);
  195. SDL_GL_GetAttribute(SDL_GL_STENCIL_SIZE, &stencilSize);
  196. SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &red);
  197. SDL_GL_GetAttribute(SDL_GL_GREEN_SIZE, &green);
  198. SDL_GL_GetAttribute(SDL_GL_BLUE_SIZE, &blue);
  199. SDL_GL_GetAttribute(SDL_GL_ALPHA_SIZE, &alpha);
  200. SDL_GL_GetAttribute(SDL_GL_ACCUM_RED_SIZE, &aRed);
  201. SDL_GL_GetAttribute(SDL_GL_ACCUM_GREEN_SIZE, &aGreen);
  202. SDL_GL_GetAttribute(SDL_GL_ACCUM_BLUE_SIZE, &aBlue);
  203. SDL_GL_GetAttribute(SDL_GL_ACCUM_ALPHA_SIZE, &aAlpha);
  204. Con::printf("OpenGL Attributes:");
  205. Con::printf(" DoubleBuffer: %d", doubleBuf);
  206. Con::printf(" BufferSize: %d, DepthSize: %d, StencilSize: %d",
  207. bufferSize, depthSize, stencilSize);
  208. Con::printf(" Red: %d, Green: %d, Blue: %d, Alpha: %d",
  209. red, green, blue, alpha);
  210. Con::printf(" Accum Red: %d, Green: %d, Blue: %d, Alpha: %d",
  211. aRed, aGreen, aBlue, aAlpha);
  212. }
  213. //------------------------------------------------------------------------------
  214. bool OpenGLDevice::setScreenMode( U32 width, U32 height, U32 bpp,
  215. bool fullScreen, bool forceIt, bool repaint )
  216. {
  217. // load resolutions, this is done lazily so that we can check the setting
  218. // of smCanSwitchBitDepth, which may be overridden by console
  219. if (mResolutionList.size()==0)
  220. loadResolutions();
  221. if (mResolutionList.size()==0)
  222. {
  223. Con::printf("No resolutions available!");
  224. return false;
  225. }
  226. if (bpp == 0)
  227. {
  228. // bpp comes in as "0" when it is set to "Default"
  229. bpp = x86UNIXState->getDesktopBpp();
  230. }
  231. if (height == 0 || width == 0)
  232. {
  233. // paranoia check. set it to the default to prevent crashing
  234. width = 800;
  235. height = 600;
  236. }
  237. U32 desktopDepth = x86UNIXState->getDesktopBpp();
  238. // if we can't switch bit depths and the requested bpp is not equal to
  239. // the desktop bpp, set bpp to the desktop bpp
  240. if (!smCanSwitchBitDepth &&
  241. bpp != desktopDepth)
  242. {
  243. bpp = desktopDepth;
  244. }
  245. bool IsInList = false;
  246. Resolution NewResolution( width, height, bpp );
  247. // See if the desired resolution is in the list
  248. if ( mResolutionList.size() )
  249. {
  250. for ( int i = 0; i < mResolutionList.size(); i++ )
  251. {
  252. if ( width == mResolutionList[i].w
  253. && height == mResolutionList[i].h
  254. && bpp == mResolutionList[i].bpp )
  255. {
  256. IsInList = true;
  257. break;
  258. }
  259. }
  260. if ( !IsInList )
  261. {
  262. Con::printf( "Selected resolution not available: %d %d %d",
  263. width, height, bpp);
  264. return false;
  265. }
  266. }
  267. else
  268. {
  269. AssertFatal( false, "No resolution list found!!" );
  270. }
  271. // Here if we found a matching resolution in the list
  272. bool needResurrect = false;
  273. if (x86UNIXState->windowCreated())
  274. {
  275. Con::printf( "Killing the texture manager..." );
  276. Game->textureKill();
  277. needResurrect = true;
  278. }
  279. // Set the desired GL Attributes
  280. SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
  281. // JMQ: NVIDIA 2802+ doesn't like this setting for stencil size
  282. // SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
  283. SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 0);
  284. SDL_GL_SetAttribute(SDL_GL_ACCUM_RED_SIZE, 0);
  285. SDL_GL_SetAttribute(SDL_GL_ACCUM_GREEN_SIZE, 0);
  286. SDL_GL_SetAttribute(SDL_GL_ACCUM_BLUE_SIZE, 0);
  287. SDL_GL_SetAttribute(SDL_GL_ACCUM_ALPHA_SIZE, 0);
  288. // SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
  289. // SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
  290. // SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 6);
  291. // SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
  292. U32 flags = SDL_OPENGL;
  293. if (fullScreen)
  294. flags |= SDL_FULLSCREEN;
  295. Con::printf( "Setting screen mode to %dx%dx%d (%s)...", width, height,
  296. bpp, ( fullScreen ? "fs" : "w" ) );
  297. // set the new video mode
  298. if (SDL_SetVideoMode(width, height, bpp, flags) == NULL)
  299. {
  300. Con::printf("Unable to set SDL Video Mode: %s", SDL_GetError());
  301. return false;
  302. }
  303. PrintGLAttributes();
  304. // clear screen here to prevent buffer garbage from being displayed when
  305. // video mode is switched
  306. glClearColor(0.0, 0.0, 0.0, 0.0);
  307. glClear(GL_COLOR_BUFFER_BIT);
  308. glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  309. if ( needResurrect )
  310. {
  311. // Reload the textures:
  312. Con::printf( "Resurrecting the texture manager..." );
  313. Game->textureResurrect();
  314. }
  315. if ( gGLState.suppSwapInterval )
  316. setVerticalSync( !Con::getBoolVariable( "$pref::Video::disableVerticalSync" ) );
  317. // reset the window in platform state
  318. SDL_SysWMinfo sysinfo;
  319. SDL_VERSION(&sysinfo.version);
  320. if (SDL_GetWMInfo(&sysinfo) == 0)
  321. {
  322. Con::printf("Unable to set SDL Video Mode: %s", SDL_GetError());
  323. return false;
  324. }
  325. x86UNIXState->setWindow(sysinfo.info.x11.window);
  326. // set various other parameters
  327. x86UNIXState->setWindowCreated(true);
  328. smCurrentRes = NewResolution;
  329. Platform::setWindowSize ( width, height );
  330. smIsFullScreen = fullScreen;
  331. Con::setBoolVariable( "$pref::Video::fullScreen", smIsFullScreen );
  332. char tempBuf[15];
  333. dSprintf( tempBuf, sizeof( tempBuf ), "%d %d %d",
  334. smCurrentRes.w, smCurrentRes.h, smCurrentRes.bpp );
  335. Con::setVariable( "$pref::Video::resolution", tempBuf );
  336. // post a TORQUE_SETVIDEOMODE user event
  337. SDL_Event event;
  338. event.type = SDL_USEREVENT;
  339. event.user.code = TORQUE_SETVIDEOMODE;
  340. event.user.data1 = NULL;
  341. event.user.data2 = NULL;
  342. SDL_PushEvent(&event);
  343. // reset the caption
  344. SDL_WM_SetCaption(x86UNIXState->getWindowName(), NULL);
  345. // repaint
  346. if ( repaint )
  347. Con::evaluate( "resetCanvas();" );
  348. return true;
  349. }
  350. //------------------------------------------------------------------------------
  351. void OpenGLDevice::swapBuffers()
  352. {
  353. SDL_GL_SwapBuffers();
  354. }
  355. //------------------------------------------------------------------------------
  356. const char* OpenGLDevice::getDriverInfo()
  357. {
  358. const char* vendorString = (const char*) glGetString( GL_VENDOR );
  359. const char* rendererString = (const char*) glGetString( GL_RENDERER );
  360. const char* versionString = (const char*) glGetString( GL_VERSION );
  361. const char* extensionsString = (const char*) glGetString( GL_EXTENSIONS );
  362. U32 bufferLen = ( vendorString ? dStrlen( vendorString ) : 0 )
  363. + ( rendererString ? dStrlen( rendererString ) : 0 )
  364. + ( versionString ? dStrlen( versionString ) : 0 )
  365. + ( extensionsString ? dStrlen( extensionsString ) : 0 )
  366. + 4;
  367. char* returnString = Con::getReturnBuffer( bufferLen );
  368. dSprintf( returnString, bufferLen, "%s\t%s\t%s\t%s",
  369. ( vendorString ? vendorString : "" ),
  370. ( rendererString ? rendererString : "" ),
  371. ( versionString ? versionString : "" ),
  372. ( extensionsString ? extensionsString : "" ) );
  373. return( returnString );
  374. }
  375. //------------------------------------------------------------------------------
  376. bool OpenGLDevice::getGammaCorrection(F32 &g)
  377. {
  378. U16 redtable[256];
  379. U16 greentable[256];
  380. U16 bluetable[256];
  381. if (SDL_GetGammaRamp(redtable, greentable, bluetable) == -1)
  382. {
  383. Con::warnf("getGammaCorrection error: %s", SDL_GetError());
  384. return false;
  385. }
  386. F32 csum = 0.0;
  387. U32 ccount = 0;
  388. for (U16 i = 0; i < 256; ++i)
  389. {
  390. if (i != 0 && redtable[i] != 0 && redtable[i] != 65535)
  391. {
  392. F64 b = (F64) i/256.0;
  393. F64 a = (F64) redtable[i]/65535.0;
  394. F32 c = (F32) (mLog(a)/mLog(b));
  395. csum += c;
  396. ++ccount;
  397. }
  398. }
  399. g = csum/ccount;
  400. return true;
  401. }
  402. //------------------------------------------------------------------------------
  403. bool OpenGLDevice::setGammaCorrection(F32 g)
  404. {
  405. U16 redtable[256];
  406. U16 greentable[256];
  407. U16 bluetable[256];
  408. for (U16 i = 0; i < 256; ++i)
  409. redtable[i] = static_cast<U16>(mPow((F32) i/256.0f, g) * 65535.0f);
  410. dMemcpy(greentable,redtable,256*sizeof(U16));
  411. dMemcpy(bluetable,redtable,256*sizeof(U16));
  412. S32 ok = SDL_SetGammaRamp(redtable, greentable, bluetable);
  413. if (ok == -1)
  414. Con::warnf("Error setting gamma correction: %s", SDL_GetError());
  415. return ok != -1;
  416. }
  417. //------------------------------------------------------------------------------
  418. bool OpenGLDevice::setVerticalSync( bool on )
  419. {
  420. Con::printf("WARNING: OpenGLDevice::setVerticalSync is unimplemented %s %d\n", __FILE__, __LINE__);
  421. return false;
  422. #if 0
  423. if ( !gGLState.suppSwapInterval )
  424. return( false );
  425. return( qwglSwapIntervalEXT( on ? 1 : 0 ) );
  426. #endif
  427. }
  428. //------------------------------------------------------------------------------
  429. DisplayDevice* OpenGLDevice::create()
  430. {
  431. return new OpenGLDevice();
  432. }
  433. #endif // 0