Adapter.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. /* Copyright (c) 2002-2012 Croteam Ltd.
  2. This program is free software; you can redistribute it and/or modify
  3. it under the terms of version 2 of the GNU General Public License as published by
  4. the Free Software Foundation
  5. This program is distributed in the hope that it will be useful,
  6. but WITHOUT ANY WARRANTY; without even the implied warranty of
  7. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  8. GNU General Public License for more details.
  9. You should have received a copy of the GNU General Public License along
  10. with this program; if not, write to the Free Software Foundation, Inc.,
  11. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
  12. #include "stdh.h"
  13. #include <Engine/Graphics/Adapter.h>
  14. #include <Engine/Graphics/GfxLibrary.h>
  15. #include <Engine/Base/Translation.h>
  16. #include <Engine/Base/Console.h>
  17. extern BOOL _bDedicatedServer;
  18. #ifdef SE1_D3D
  19. extern const D3DDEVTYPE d3dDevType;
  20. #endif // SE1_D3D
  21. // list of all modes avaliable through CDS
  22. static CListHead _lhCDSModes;
  23. class CResolution {
  24. public:
  25. PIX re_pixSizeI;
  26. PIX re_pixSizeJ;
  27. };
  28. static CResolution _areResolutions[] =
  29. {
  30. { 320, 240 },
  31. { 400, 300 },
  32. { 480, 360 },
  33. { 512, 384 },
  34. { 640, 480 },
  35. { 720, 540 },
  36. { 720, 576 },
  37. { 800, 600 },
  38. { 960, 720 },
  39. { 1024, 768 },
  40. { 1152, 864 },
  41. { 1280, 960 },
  42. { 1280, 1024 },
  43. { 1600, 1200 },
  44. { 1792, 1344 },
  45. { 1856, 1392 },
  46. { 1920, 1440 },
  47. { 2048, 1536 },
  48. // matrox dualhead modes
  49. { 1280, 480 },
  50. { 1600, 600 },
  51. { 2048, 768 },
  52. // NTSC HDTV widescreen
  53. { 848, 480 },
  54. { 856, 480 },
  55. };
  56. // THIS NUMBER MUST NOT BE OVER 25! (otherwise change it in adapter.h)
  57. static const INDEX MAX_RESOLUTIONS = sizeof(_areResolutions)/sizeof(_areResolutions[0]);
  58. // initialize CDS support (enumerate modes at startup)
  59. void CGfxLibrary::InitAPIs(void)
  60. {
  61. // no need for gfx when dedicated server is on
  62. if( _bDedicatedServer) return;
  63. CDisplayAdapter *pda;
  64. INDEX iResolution;
  65. // detect current mode and print to console
  66. DEVMODE devmode;
  67. memset( &devmode, 0, sizeof(devmode));
  68. devmode.dmSize = sizeof(devmode);
  69. LONG lRes = EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &devmode);
  70. CPrintF( TRANS("Current display: '%s' version %d - %dx%dx%d\n\n"),
  71. devmode.dmDeviceName, devmode.dmDriverVersion,
  72. devmode.dmPelsWidth, devmode.dmPelsHeight, devmode.dmBitsPerPel);
  73. // fill OpenGL adapter info
  74. gl_gaAPI[GAT_OGL].ga_ctAdapters = 1;
  75. gl_gaAPI[GAT_OGL].ga_iCurrentAdapter = 0;
  76. pda = &gl_gaAPI[GAT_OGL].ga_adaAdapter[0];
  77. pda->da_ulFlags = DAF_USEGDIFUNCTIONS;
  78. pda->da_strVendor = TRANS( "unknown");
  79. pda->da_strRenderer = TRANS( "Default ICD");
  80. pda->da_strVersion = "1.1+";
  81. // detect modes for OpenGL ICD
  82. pda->da_ctDisplayModes = 0;
  83. pda->da_iCurrentDisplayMode = -1;
  84. // enumerate modes thru resolution list
  85. for( iResolution=0; iResolution<MAX_RESOLUTIONS; iResolution++)
  86. {
  87. DEVMODE devmode;
  88. memset( &devmode, 0, sizeof(devmode));
  89. CResolution &re = _areResolutions[iResolution];
  90. // ask windows if they could set the mode
  91. devmode.dmSize = sizeof(devmode);
  92. devmode.dmPelsWidth = re.re_pixSizeI;
  93. devmode.dmPelsHeight = re.re_pixSizeJ;
  94. devmode.dmDisplayFlags = CDS_FULLSCREEN;
  95. devmode.dmFields = DM_PELSWIDTH|DM_PELSHEIGHT|DM_DISPLAYFLAGS;
  96. LONG lRes = ChangeDisplaySettings( &devmode, CDS_TEST|CDS_FULLSCREEN);
  97. // skip if not successfull
  98. if( lRes!=DISP_CHANGE_SUCCESSFUL) continue;
  99. // make a new display mode
  100. CDisplayMode &dm = pda->da_admDisplayModes[pda->da_ctDisplayModes];
  101. dm.dm_pixSizeI = re.re_pixSizeI;
  102. dm.dm_pixSizeJ = re.re_pixSizeJ;
  103. dm.dm_ddDepth = DD_DEFAULT;
  104. pda->da_ctDisplayModes++;
  105. }
  106. // detect presence of 3Dfx standalone OpenGL driver (for Voodoo1/2)
  107. char *strDummy;
  108. char strBuffer[_MAX_PATH+1];
  109. int iRes = SearchPathA( NULL, "3DFXVGL.DLL", NULL, _MAX_PATH, strBuffer, &strDummy);
  110. // if present
  111. if(iRes) {
  112. // set adapter and force some enumeration of voodoo1/2 display modes
  113. gl_gaAPI[GAT_OGL].ga_ctAdapters++;
  114. pda = &gl_gaAPI[GAT_OGL].ga_adaAdapter[1];
  115. pda->da_ctDisplayModes = 4; // voodoos have only 4 display modes
  116. pda->da_ulFlags = DAF_ONEWINDOW | DAF_FULLSCREENONLY | DAF_16BITONLY;
  117. pda->da_strVendor = "3Dfx";
  118. pda->da_strRenderer = "3Dfx Voodoo2";
  119. pda->da_strVersion = "1.1+";
  120. CDisplayMode *adm = &pda->da_admDisplayModes[0];
  121. adm[0].dm_pixSizeI = 512; adm[0].dm_pixSizeJ = 384; adm[0].dm_ddDepth = DD_16BIT;
  122. adm[1].dm_pixSizeI = 640; adm[1].dm_pixSizeJ = 480; adm[1].dm_ddDepth = DD_16BIT;
  123. adm[2].dm_pixSizeI = 800; adm[2].dm_pixSizeJ = 600; adm[2].dm_ddDepth = DD_16BIT;
  124. adm[3].dm_pixSizeI = 1024; adm[3].dm_pixSizeJ = 768; adm[3].dm_ddDepth = DD_16BIT;
  125. }
  126. // try to init Direct3D 8
  127. #ifdef SE1_D3D
  128. BOOL bRes = InitDriver_D3D();
  129. if( !bRes) return; // didn't made it?
  130. // determine DX8 adapters and display modes
  131. const INDEX ctMaxAdapters = gl_pD3D->GetAdapterCount();
  132. INDEX &ctAdapters = gl_gaAPI[GAT_D3D].ga_ctAdapters;
  133. ctAdapters = 0;
  134. for( INDEX iAdapter=0; iAdapter<ctMaxAdapters; iAdapter++)
  135. {
  136. pda = &gl_gaAPI[1].ga_adaAdapter[ctAdapters];
  137. pda->da_ulFlags = NONE;
  138. pda->da_ctDisplayModes = 0;
  139. INDEX ctModes = gl_pD3D->GetAdapterModeCount(iAdapter);
  140. INDEX iMode;
  141. HRESULT hr;
  142. // check whether 32-bits rendering modes are supported
  143. hr = gl_pD3D->CheckDeviceType( iAdapter, d3dDevType, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, FALSE);
  144. if( hr!=D3D_OK) {
  145. hr = gl_pD3D->CheckDeviceType( iAdapter, d3dDevType, D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, FALSE);
  146. if( hr!=D3D_OK) pda->da_ulFlags |= DAF_16BITONLY;
  147. }
  148. // check whether windowed rendering modes are supported
  149. D3DCAPS8 d3dCaps;
  150. gl_pD3D->GetDeviceCaps( iAdapter, d3dDevType, &d3dCaps);
  151. if( !(d3dCaps.Caps2 & D3DCAPS2_CANRENDERWINDOWED)) pda->da_ulFlags |= DAF_FULLSCREENONLY;
  152. // enumerate modes thru resolution list
  153. for( iResolution=0; iResolution<MAX_RESOLUTIONS; iResolution++)
  154. {
  155. CResolution &re = _areResolutions[iResolution];
  156. for( iMode=0; iMode<ctModes; iMode++) {
  157. // if resolution matches and display depth is 16 or 32 bit
  158. D3DDISPLAYMODE d3dDisplayMode;
  159. gl_pD3D->EnumAdapterModes( iAdapter, iMode, &d3dDisplayMode);
  160. if( d3dDisplayMode.Width==re.re_pixSizeI && d3dDisplayMode.Height==re.re_pixSizeJ
  161. && (d3dDisplayMode.Format==D3DFMT_A8R8G8B8 || d3dDisplayMode.Format==D3DFMT_X8R8G8B8
  162. || d3dDisplayMode.Format==D3DFMT_A1R5G5B5 || d3dDisplayMode.Format==D3DFMT_X1R5G5B5
  163. || d3dDisplayMode.Format==D3DFMT_R5G6B5)) {
  164. hr = gl_pD3D->CheckDeviceType( iAdapter, d3dDevType, d3dDisplayMode.Format, d3dDisplayMode.Format, FALSE);
  165. if( hr!=D3D_OK) continue;
  166. // make a new display mode
  167. CDisplayMode &dm = pda->da_admDisplayModes[pda->da_ctDisplayModes];
  168. dm.dm_pixSizeI = re.re_pixSizeI;
  169. dm.dm_pixSizeJ = re.re_pixSizeJ;
  170. dm.dm_ddDepth = DD_DEFAULT;
  171. pda->da_ctDisplayModes++;
  172. break;
  173. }
  174. }
  175. }
  176. // get adapter identifier
  177. ctAdapters++;
  178. D3DADAPTER_IDENTIFIER8 d3dAdapterIdentifier;
  179. gl_pD3D->GetAdapterIdentifier( iAdapter, D3DENUM_NO_WHQL_LEVEL, &d3dAdapterIdentifier);
  180. pda->da_strVendor = "MS DirectX 8";
  181. pda->da_strRenderer = d3dAdapterIdentifier.Description;
  182. pda->da_strVersion.PrintF("%d.%d.%d.%d", d3dAdapterIdentifier.DriverVersion.HighPart >>16,
  183. d3dAdapterIdentifier.DriverVersion.HighPart & 0xFFFF,
  184. d3dAdapterIdentifier.DriverVersion.LowPart >>16,
  185. d3dAdapterIdentifier.DriverVersion.LowPart & 0xFFFF);
  186. }
  187. // shutdown DX8 (we'll start it again if needed)
  188. D3DRELEASE( gl_pD3D, TRUE);
  189. if( gl_hiDriver!=NONE) FreeLibrary(gl_hiDriver);
  190. gl_hiDriver = NONE;
  191. #endif // SE1_D3D
  192. }
  193. // get list of all modes avaliable through CDS -- do not modify/free the returned list
  194. CListHead &CDS_GetModes(void)
  195. {
  196. return _lhCDSModes;
  197. }
  198. // set given display mode
  199. BOOL CDS_SetMode( PIX pixSizeI, PIX pixSizeJ, enum DisplayDepth dd)
  200. {
  201. // no need for gfx when dedicated server is on
  202. if( _bDedicatedServer) return FALSE;
  203. // prepare general mode parameters
  204. DEVMODE devmode;
  205. memset(&devmode, 0, sizeof(devmode));
  206. devmode.dmSize = sizeof(devmode);
  207. devmode.dmPelsWidth = pixSizeI;
  208. devmode.dmPelsHeight = pixSizeJ;
  209. devmode.dmDisplayFlags = CDS_FULLSCREEN;
  210. devmode.dmFields = DM_PELSWIDTH|DM_PELSHEIGHT|DM_DISPLAYFLAGS;
  211. extern INDEX gap_iRefreshRate;
  212. if( gap_iRefreshRate>0) {
  213. devmode.dmFields |= DM_DISPLAYFREQUENCY;
  214. devmode.dmDisplayFrequency = gap_iRefreshRate;
  215. }
  216. // determine bits per pixel to try to set
  217. SLONG slBPP2 = 0;
  218. switch(dd) {
  219. case DD_16BIT:
  220. devmode.dmBitsPerPel = 16;
  221. slBPP2 = 15;
  222. devmode.dmFields |= DM_BITSPERPEL;
  223. break;
  224. case DD_32BIT:
  225. devmode.dmBitsPerPel = 32;
  226. slBPP2 = 24;
  227. devmode.dmFields |= DM_BITSPERPEL;
  228. break;
  229. case DD_DEFAULT:
  230. NOTHING;
  231. break;
  232. default:
  233. ASSERT(FALSE);
  234. NOTHING;
  235. }
  236. // try to set primary depth
  237. LONG lRes = ChangeDisplaySettings(&devmode, CDS_FULLSCREEN);
  238. // if failed
  239. if( lRes!=DISP_CHANGE_SUCCESSFUL) {
  240. // try to set secondary depth
  241. devmode.dmBitsPerPel = slBPP2;
  242. LONG lRes2 = ChangeDisplaySettings(&devmode, CDS_FULLSCREEN);
  243. // if failed
  244. if( lRes2!=DISP_CHANGE_SUCCESSFUL) {
  245. CTString strError;
  246. switch(lRes) {
  247. case DISP_CHANGE_SUCCESSFUL: strError = "DISP_CHANGE_SUCCESSFUL"; break;
  248. case DISP_CHANGE_RESTART: strError = "DISP_CHANGE_RESTART"; break;
  249. case DISP_CHANGE_BADFLAGS: strError = "DISP_CHANGE_BADFLAGS"; break;
  250. case DISP_CHANGE_BADPARAM: strError = "DISP_CHANGE_BADPARAM"; break;
  251. case DISP_CHANGE_FAILED: strError = "DISP_CHANGE_FAILED"; break;
  252. case DISP_CHANGE_BADMODE: strError = "DISP_CHANGE_BADMODE"; break;
  253. case DISP_CHANGE_NOTUPDATED: strError = "DISP_CHANGE_NOTUPDATED"; break;
  254. default: strError.PrintF("%d", lRes); break;
  255. }
  256. CPrintF(TRANS("CDS error: %s\n"), strError);
  257. return FALSE;
  258. }
  259. }
  260. // report
  261. CPrintF(TRANS(" CDS: mode set to %dx%dx%d\n"), pixSizeI, pixSizeJ, devmode.dmBitsPerPel);
  262. return TRUE;
  263. }
  264. // reset windows to mode chosen by user within windows diplay properties
  265. void CDS_ResetMode(void)
  266. {
  267. // no need for gfx when dedicated server is on
  268. if( _bDedicatedServer) return;
  269. LONG lRes = ChangeDisplaySettings( NULL, 0);
  270. ASSERT(lRes==DISP_CHANGE_SUCCESSFUL);
  271. CPrintF(TRANS(" CDS: mode reset to original desktop settings\n"));
  272. }