Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

630 lines
20 KiB

  1. //========= Copyright 1996-2009, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Defines a group of app systems that all have the same lifetime
  4. // that need to be connected/initialized, etc. in a well-defined order
  5. //
  6. // $Revision: $
  7. // $NoKeywords: $
  8. //=============================================================================//
  9. //===============================================================================
  10. GLMRendererInfo::GLMRendererInfo( void )
  11. {
  12. m_display = NULL;
  13. Q_memset( &m_info, 0, sizeof( m_info ) );
  14. }
  15. GLMRendererInfo::~GLMRendererInfo( void )
  16. {
  17. SDLAPP_FUNC;
  18. if (m_display)
  19. {
  20. delete m_display;
  21. m_display = NULL;
  22. }
  23. }
  24. // !!! FIXME: sync this function with the Mac version in case anything important has changed.
  25. void GLMRendererInfo::Init( GLMRendererInfoFields *info )
  26. {
  27. SDLAPP_FUNC;
  28. m_info = *info;
  29. m_display = NULL;
  30. m_info.m_fullscreen = 0;
  31. m_info.m_accelerated = 1;
  32. m_info.m_windowed = 1;
  33. m_info.m_ati = true;
  34. m_info.m_atiNewer = true;
  35. m_info.m_hasGammaWrites = true;
  36. // If you haven't created a GL context by now (and initialized gGL), you're about to crash.
  37. m_info.m_hasMixedAttachmentSizes = gGL->m_bHave_GL_ARB_framebuffer_object;
  38. m_info.m_hasBGRA = gGL->m_bHave_GL_EXT_vertex_array_bgra;
  39. // !!! FIXME: what do these do on the Mac?
  40. m_info.m_hasNewFullscreenMode = false;
  41. m_info.m_hasNativeClipVertexMode = true;
  42. // if user disabled them
  43. if (CommandLine()->FindParm("-glmdisableclipplanes"))
  44. {
  45. m_info.m_hasNativeClipVertexMode = false;
  46. }
  47. // or maybe enabled them..
  48. if (CommandLine()->FindParm("-glmenableclipplanes"))
  49. {
  50. m_info.m_hasNativeClipVertexMode = true;
  51. }
  52. m_info.m_hasOcclusionQuery = gGL->m_bHave_GL_ARB_occlusion_query;
  53. m_info.m_hasFramebufferBlit = gGL->m_bHave_GL_EXT_framebuffer_blit || gGL->m_bHave_GL_ARB_framebuffer_object;
  54. GLint nMaxAniso = 0;
  55. gGL->glGetIntegerv( GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &nMaxAniso );
  56. m_info.m_maxAniso = clamp<int>( nMaxAniso, 0, 16 );
  57. // We don't currently used bindable uniforms, but I've been experimenting with them so I might as well check this in just in case they turn out to be useful.
  58. m_info.m_hasBindableUniforms = gGL->m_bHave_GL_EXT_bindable_uniform;
  59. m_info.m_hasBindableUniforms = false; // !!! FIXME hardwiring this path to false until we see how to accelerate it properly
  60. m_info.m_maxVertexBindableUniforms = 0;
  61. m_info.m_maxFragmentBindableUniforms = 0;
  62. m_info.m_maxBindableUniformSize = 0;
  63. if (m_info.m_hasBindableUniforms)
  64. {
  65. gGL->glGetIntegerv(GL_MAX_VERTEX_BINDABLE_UNIFORMS_EXT, &m_info.m_maxVertexBindableUniforms);
  66. gGL->glGetIntegerv(GL_MAX_FRAGMENT_BINDABLE_UNIFORMS_EXT, &m_info.m_maxFragmentBindableUniforms);
  67. gGL->glGetIntegerv(GL_MAX_BINDABLE_UNIFORM_SIZE_EXT, &m_info.m_maxBindableUniformSize);
  68. if ( ( m_info.m_maxVertexBindableUniforms < 1 ) || ( m_info.m_maxFragmentBindableUniforms < 1 ) || ( m_info.m_maxBindableUniformSize < ( sizeof( float ) * 4 * 256 ) ) )
  69. {
  70. m_info.m_hasBindableUniforms = false;
  71. }
  72. }
  73. m_info.m_hasUniformBuffers = gGL->m_bHave_GL_ARB_uniform_buffer;
  74. m_info.m_hasPerfPackage1 = true; // this flag is Mac-specific. We do slower things if you don't have Mac OS X 10.x.y or later. Linux always does the fast path!
  75. //-------------------------------------------------------------------
  76. // runtime options that aren't negotiable once set
  77. m_info.m_hasDualShaders = CommandLine()->FindParm("-glmdualshaders") != 0;
  78. //-------------------------------------------------------------------
  79. // "can'ts "
  80. #if defined( OSX )
  81. m_info.m_cantBlitReliably = m_info.m_intel; //FIXME X3100&10.6.3 has problems blitting.. adjust this if bug fixed in 10.6.4
  82. #else
  83. // m_cantBlitReliably path doesn't work right now, and the Intel path is different for us on Linux/Win7 anyway
  84. m_info.m_cantBlitReliably = false;
  85. #endif
  86. if (CommandLine()->FindParm("-glmenabletrustblit"))
  87. {
  88. m_info.m_cantBlitReliably = false; // we trust the blit, so set the cant-blit cap to false
  89. }
  90. if (CommandLine()->FindParm("-glmdisabletrustblit"))
  91. {
  92. m_info.m_cantBlitReliably = true; // we do not trust the blit, so set the cant-blit cap to true
  93. }
  94. // MSAA resolve issues
  95. m_info.m_cantResolveFlipped = false;
  96. #if defined( OSX )
  97. m_info.m_cantResolveScaled = true; // generally true until new extension ships
  98. #else
  99. // DON'T just slam this to false and run without first testing with -gl_debug enabled on NVidia/AMD/etc.
  100. // This path needs the m_bHave_GL_EXT_framebuffer_multisample_blit_scaled extension.
  101. m_info.m_cantResolveScaled = true;
  102. if ( gGL->m_bHave_GL_EXT_framebuffer_multisample_blit_scaled )
  103. {
  104. m_info.m_cantResolveScaled = false;
  105. }
  106. #endif
  107. // gamma decode impacting shader codegen
  108. m_info.m_costlyGammaFlips = false;
  109. }
  110. void GLMRendererInfo::PopulateDisplays()
  111. {
  112. SDLAPP_FUNC;
  113. Assert( !m_display );
  114. m_display = new GLMDisplayInfo;
  115. // Populate display mode table.
  116. m_display->PopulateModes();
  117. }
  118. void GLMRendererInfo::Dump( int which )
  119. {
  120. SDLAPP_FUNC;
  121. GLMPRINTF(("\n #%d: GLMRendererInfo @ %p, renderer-id=(%08x) display-mask=%08x vram=%dMB",
  122. which, this,
  123. m_info.m_rendererID,
  124. m_info.m_displayMask,
  125. m_info.m_vidMemory >> 20
  126. ));
  127. GLMPRINTF(("\n VendorID=%04x DeviceID=%04x Model=%s",
  128. m_info.m_pciVendorID,
  129. m_info.m_pciDeviceID,
  130. m_info.m_pciModelString
  131. ));
  132. m_display->Dump( which );
  133. }
  134. GLMDisplayDB::GLMDisplayDB ()
  135. {
  136. SDLAPP_FUNC;
  137. m_renderer.m_display = NULL;
  138. }
  139. GLMDisplayDB::~GLMDisplayDB ( void )
  140. {
  141. SDLAPP_FUNC;
  142. if ( m_renderer.m_display )
  143. {
  144. delete m_renderer.m_display;
  145. m_renderer.m_display = NULL;
  146. }
  147. }
  148. #ifndef GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX
  149. #define GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX 0x9047
  150. #endif
  151. #ifndef GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX
  152. #define GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX 0x9048
  153. #endif
  154. #ifndef GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX
  155. #define GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX 0x9049
  156. #endif
  157. #ifndef GL_VBO_FREE_MEMORY_ATI
  158. #define GL_VBO_FREE_MEMORY_ATI 0x87FB
  159. #endif
  160. #ifndef GL_TEXTURE_FREE_MEMORY_ATI
  161. #define GL_TEXTURE_FREE_MEMORY_ATI 0x87FC
  162. #endif
  163. #ifndef GL_RENDERBUFFER_FREE_MEMORY_ATI
  164. #define GL_RENDERBUFFER_FREE_MEMORY_ATI 0x87FD
  165. #endif
  166. void GLMDisplayDB::PopulateRenderers( void )
  167. {
  168. SDLAPP_FUNC;
  169. Assert( !m_renderer.m_display );
  170. GLMRendererInfoFields fields;
  171. memset( &fields, 0, sizeof(fields) );
  172. // Assume 512MB of available video memory
  173. fields.m_vidMemory = 512 * 1024 * 1024;
  174. DebugPrintf( "GL_NVX_gpu_memory_info: %s\n", gGL->m_bHave_GL_NVX_gpu_memory_info ? "AVAILABLE" : "UNAVAILABLE" );
  175. DebugPrintf( "GL_ATI_meminfo: %s\n", gGL->m_bHave_GL_ATI_meminfo ? "AVAILABLE" : "UNAVAILABLE" );
  176. if ( gGL->m_bHave_GL_NVX_gpu_memory_info )
  177. {
  178. gGL->glGetError();
  179. GLint nTotalDedicated = 0, nTotalAvail = 0, nCurrentAvail = 0;
  180. gGL->glGetIntegerv( GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX, &nTotalDedicated );
  181. gGL->glGetIntegerv( GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, &nTotalAvail );
  182. gGL->glGetIntegerv( GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &nCurrentAvail );
  183. if ( gGL->glGetError() )
  184. {
  185. DebugPrintf( "GL_NVX_gpu_memory_info: Failed retrieving available GPU memory\n" );
  186. }
  187. else
  188. {
  189. DebugPrintf( "GL_NVX_gpu_memory_info: Total Dedicated: %u, Total Avail: %u, Current Avail: %u\n", nTotalDedicated, nTotalAvail, nCurrentAvail );
  190. // Try to do something reasonable. Should we report dedicated or total available to the engine here?
  191. // For now, just take the MAX of both.
  192. uint64 nActualAvail = static_cast<uint64>( MAX( nTotalAvail, nTotalDedicated ) ) * 1024;
  193. fields.m_vidMemory = static_cast< GLint >( MIN( nActualAvail, 0x7FFFFFFF ) );
  194. }
  195. }
  196. else if ( gGL->m_bHave_GL_ATI_meminfo )
  197. {
  198. // As of 10/8/12 this extension is only available under Linux and Windows FireGL parts.
  199. gGL->glGetError();
  200. GLint nAvail[4] = { 0, 0, 0, 0 };
  201. gGL->glGetIntegerv( GL_TEXTURE_FREE_MEMORY_ATI, nAvail );
  202. if ( gGL->glGetError() )
  203. {
  204. DebugPrintf( "GL_ATI_meminfo: Failed retrieving available GPU memory\n" );
  205. }
  206. else
  207. {
  208. // param[0] - total memory free in the pool
  209. // param[1] - largest available free block in the pool
  210. // param[2] - total auxiliary memory free
  211. // param[3] - largest auxiliary free block
  212. DebugPrintf( "GL_ATI_meminfo: GL_TEXTURE_FREE_MEMORY_ATI: Total Free: %i, Largest Avail: %i, Total Aux: %i, Largest Aux Avail: %i\n",
  213. nAvail[0], nAvail[1], nAvail[2], nAvail[3] );
  214. uint64 nActualAvail = static_cast<uint64>( nAvail[0] ) * 1024;
  215. fields.m_vidMemory = static_cast< GLint >( MIN( nActualAvail, 0x7FFFFFFF ) );
  216. }
  217. }
  218. // Clamp the min amount of video memory to 256MB in case a query returned something bogus, or we interpreted it badly.
  219. fields.m_vidMemory = MAX( fields.m_vidMemory, 128 * 1024 * 1024 );
  220. fields.m_texMemory = fields.m_vidMemory;
  221. fields.m_pciVendorID = GLM_OPENGL_VENDOR_ID;
  222. fields.m_pciDeviceID = GLM_OPENGL_DEFAULT_DEVICE_ID;
  223. if ( ( gGL->m_nDriverProvider == cGLDriverProviderIntel ) || ( gGL->m_nDriverProvider == cGLDriverProviderIntelOpenSource ) )
  224. {
  225. fields.m_pciDeviceID = GLM_OPENGL_LOW_PERF_DEVICE_ID;
  226. }
  227. /* fields.m_colorModes = (uint)-1;
  228. fields.m_bufferModes = (uint)-1;
  229. fields.m_depthModes = (uint)-1;
  230. fields.m_stencilModes = (uint)-1;
  231. fields.m_maxAuxBuffers = (uint)128;
  232. fields.m_maxSampleBuffers = (uint)128;
  233. fields.m_maxSamples = (uint)2048;
  234. fields.m_sampleModes = (uint)128;
  235. fields.m_sampleAlpha = (uint)32;
  236. */
  237. GLint nMaxMultiSamples = 0;
  238. gGL->glGetIntegerv( GL_MAX_SAMPLES_EXT, &nMaxMultiSamples );
  239. fields.m_maxSamples = clamp<int>( nMaxMultiSamples, 0, 8 );
  240. DebugPrintf( "GL_MAX_SAMPLES_EXT: %i\n", nMaxMultiSamples );
  241. // We only have one GLMRendererInfo on Linux, unlike Mac OS X. Whatever libGL.so wants to do, we go with it.
  242. m_renderer.Init( &fields );
  243. // then go back and ask each renderer to populate its display info table.
  244. m_renderer.PopulateDisplays();
  245. }
  246. void GLMDisplayDB::PopulateFakeAdapters( uint realRendererIndex ) // fake adapters = one real adapter times however many displays are on it
  247. {
  248. SDLAPP_FUNC;
  249. Assert( realRendererIndex == 0 );
  250. }
  251. void GLMDisplayDB::Populate(void)
  252. {
  253. SDLAPP_FUNC;
  254. this->PopulateRenderers();
  255. this->PopulateFakeAdapters( 0 );
  256. #if GLMDEBUG
  257. this->Dump();
  258. #endif
  259. }
  260. int GLMDisplayDB::GetFakeAdapterCount( void )
  261. {
  262. SDLAPP_FUNC;
  263. return 1;
  264. }
  265. bool GLMDisplayDB::GetFakeAdapterInfo( int fakeAdapterIndex, int *rendererOut, int *displayOut, GLMRendererInfoFields *rendererInfoOut, GLMDisplayInfoFields *displayInfoOut )
  266. {
  267. SDLAPP_FUNC;
  268. if (fakeAdapterIndex >= GetFakeAdapterCount() )
  269. {
  270. *rendererOut = 0;
  271. *displayOut = 0;
  272. return true; // fail
  273. }
  274. *rendererOut = 0;
  275. *displayOut = 0;
  276. bool rendResult = GetRendererInfo( *rendererOut, rendererInfoOut );
  277. bool dispResult = GetDisplayInfo( *rendererOut, *displayOut, displayInfoOut );
  278. return rendResult || dispResult;
  279. }
  280. int GLMDisplayDB::GetRendererCount( void )
  281. {
  282. SDLAPP_FUNC;
  283. return 1;
  284. }
  285. bool GLMDisplayDB::GetRendererInfo( int rendererIndex, GLMRendererInfoFields *infoOut )
  286. {
  287. SDLAPP_FUNC;
  288. memset( infoOut, 0, sizeof( GLMRendererInfoFields ) );
  289. if (rendererIndex >= GetRendererCount())
  290. return true; // fail
  291. *infoOut = m_renderer.m_info;
  292. return false;
  293. }
  294. int GLMDisplayDB::GetDisplayCount( int rendererIndex )
  295. {
  296. SDLAPP_FUNC;
  297. if (rendererIndex >= GetRendererCount())
  298. {
  299. Assert( 0 );
  300. return 0; // fail
  301. }
  302. return 1;
  303. }
  304. bool GLMDisplayDB::GetDisplayInfo( int rendererIndex, int displayIndex, GLMDisplayInfoFields *infoOut )
  305. {
  306. SDLAPP_FUNC;
  307. memset( infoOut, 0, sizeof( GLMDisplayInfoFields ) );
  308. if (rendererIndex >= GetRendererCount())
  309. return true; // fail
  310. if (displayIndex >= GetDisplayCount(rendererIndex))
  311. return true; // fail
  312. *infoOut = m_renderer.m_display->m_info;
  313. return false;
  314. }
  315. int GLMDisplayDB::GetModeCount( int rendererIndex, int displayIndex )
  316. {
  317. SDLAPP_FUNC;
  318. if (rendererIndex >= GetRendererCount())
  319. return 0; // fail
  320. if (displayIndex >= GetDisplayCount(rendererIndex))
  321. return 0; // fail
  322. return m_renderer.m_display->m_modes->Count();
  323. }
  324. bool GLMDisplayDB::GetModeInfo( int rendererIndex, int displayIndex, int modeIndex, GLMDisplayModeInfoFields *infoOut )
  325. {
  326. SDLAPP_FUNC;
  327. memset( infoOut, 0, sizeof( GLMDisplayModeInfoFields ) );
  328. if ( rendererIndex >= GetRendererCount())
  329. return true; // fail
  330. if (displayIndex >= GetDisplayCount( rendererIndex ) )
  331. return true; // fail
  332. if ( modeIndex >= GetModeCount( rendererIndex, displayIndex ) )
  333. return true; // fail
  334. if ( modeIndex >= 0 )
  335. {
  336. GLMDisplayMode *displayModeInfo = m_renderer.m_display->m_modes->Element( modeIndex );
  337. *infoOut = displayModeInfo->m_info;
  338. }
  339. else
  340. {
  341. const GLMDisplayInfoFields &info = m_renderer.m_display->m_info;
  342. infoOut->m_modePixelWidth = info.m_displayPixelWidth;
  343. infoOut->m_modePixelHeight = info.m_displayPixelHeight;
  344. infoOut->m_modeRefreshHz = 0;
  345. //return true; // fail
  346. }
  347. return false;
  348. }
  349. void GLMDisplayDB::Dump( void )
  350. {
  351. SDLAPP_FUNC;
  352. GLMPRINTF(("\n GLMDisplayDB @ %p ",this ));
  353. m_renderer.Dump( 0 );
  354. }
  355. //===============================================================================
  356. GLMDisplayInfo::GLMDisplayInfo()
  357. {
  358. SDLAPP_FUNC;
  359. m_modes = NULL;
  360. int Width, Height;
  361. GetLargestDisplaySize( Width, Height );
  362. m_info.m_displayPixelWidth = ( uint )Width;
  363. m_info.m_displayPixelHeight = ( uint )Height;
  364. }
  365. GLMDisplayInfo::~GLMDisplayInfo( void )
  366. {
  367. SDLAPP_FUNC;
  368. }
  369. extern "C" int DisplayModeSortFunction( GLMDisplayMode * const *A, GLMDisplayMode * const *B )
  370. {
  371. SDLAPP_FUNC;
  372. int bigger = -1;
  373. int smaller = 1; // adjust these for desired ordering
  374. // check refreshrate - higher should win
  375. if ( (*A)->m_info.m_modeRefreshHz > (*B)->m_info.m_modeRefreshHz )
  376. {
  377. return bigger;
  378. }
  379. else if ( (*A)->m_info.m_modeRefreshHz < (*B)->m_info.m_modeRefreshHz )
  380. {
  381. return smaller;
  382. }
  383. // check area - larger mode should win
  384. int areaa = (*A)->m_info.m_modePixelWidth * (*A)->m_info.m_modePixelHeight;
  385. int areab = (*B)->m_info.m_modePixelWidth * (*B)->m_info.m_modePixelHeight;
  386. if ( areaa > areab )
  387. {
  388. return bigger;
  389. }
  390. else if ( areaa < areab )
  391. {
  392. return smaller;
  393. }
  394. return 0; // equal rank
  395. }
  396. void GLMDisplayInfo::PopulateModes( void )
  397. {
  398. SDLAPP_FUNC;
  399. Assert( !m_modes );
  400. m_modes = new CUtlVector< GLMDisplayMode* >;
  401. int nummodes = SDL_GetNumVideoDisplays();
  402. for ( int i = 0; i < nummodes; i++ )
  403. {
  404. SDL_Rect rect = { 0, 0, 0, 0 };
  405. if ( !SDL_GetDisplayBounds( i, &rect ) && rect.w && rect.h )
  406. {
  407. m_modes->AddToTail( new GLMDisplayMode( rect.w, rect.h, 0 ) );
  408. }
  409. }
  410. // Add a big pile of window resolutions.
  411. static const struct
  412. {
  413. uint w;
  414. uint h;
  415. } s_Resolutions[] =
  416. {
  417. { 640, 480 }, // 4x3
  418. { 800, 600 },
  419. { 1024, 768 },
  420. { 1152, 864 },
  421. { 1280, 960 },
  422. { 1600, 1200 },
  423. { 1920, 1440 },
  424. { 2048, 1536 },
  425. { 1280, 720 }, // 16x9
  426. { 1366, 768 },
  427. { 1600, 900 },
  428. { 1920, 1080 },
  429. { 720, 480 }, // 16x10
  430. { 1280, 800 },
  431. { 1680, 1050 },
  432. { 1920, 1200 },
  433. { 2560, 1600 },
  434. };
  435. for ( int i = 0; i < ARRAYSIZE( s_Resolutions ); i++ )
  436. {
  437. uint w = s_Resolutions[ i ].w;
  438. uint h = s_Resolutions[ i ].h;
  439. if ( ( w <= m_info.m_displayPixelWidth ) && ( h <= m_info.m_displayPixelHeight ) )
  440. {
  441. m_modes->AddToTail( new GLMDisplayMode( w, h, 0 ) );
  442. if ( ( w * 2 <= m_info.m_displayPixelWidth ) && ( h * 2 < m_info.m_displayPixelHeight ) )
  443. {
  444. // Add double of everything also - Retina proofing hopefully.
  445. m_modes->AddToTail( new GLMDisplayMode( w * 2, h * 2, 0 ) );
  446. }
  447. }
  448. }
  449. m_modes->Sort( DisplayModeSortFunction );
  450. // remove dupes.
  451. nummodes = m_modes->Count();
  452. int i = 1; // not zero!
  453. while (i < nummodes)
  454. {
  455. GLMDisplayModeInfoFields& info0 = m_modes->Element( i - 1 )->m_info;
  456. GLMDisplayModeInfoFields& info1 = m_modes->Element( i )->m_info;
  457. if ( ( info0.m_modePixelWidth == info1.m_modePixelWidth ) &&
  458. ( info0.m_modePixelHeight == info1.m_modePixelHeight ) &&
  459. ( info0.m_modeRefreshHz == info1.m_modeRefreshHz ) )
  460. {
  461. m_modes->Remove(i);
  462. nummodes--;
  463. }
  464. else
  465. {
  466. i++;
  467. }
  468. }
  469. }
  470. void GLMDisplayInfo::Dump( int which )
  471. {
  472. SDLAPP_FUNC;
  473. GLMPRINTF(("\n #%d: GLMDisplayInfo @ %08x, pixwidth=%d pixheight=%d",
  474. which, (int)this, m_info.m_displayPixelWidth, m_info.m_displayPixelHeight ));
  475. FOR_EACH_VEC( *m_modes, i )
  476. {
  477. ( *m_modes )[i]->Dump(i);
  478. }
  479. }