2
0

CmWin32GLSupport.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587
  1. #include "CmException.h"
  2. #include <algorithm>
  3. #include "CmWin32GLSupport.h"
  4. #include "CmGLTexture.h"
  5. #include "CmWin32Window.h"
  6. #include <GL/wglext.h>
  7. using namespace CamelotEngine;
  8. #if CM_THREAD_SUPPORT != 1
  9. GLenum wglewContextInit (CamelotEngine::GLSupport *glSupport);
  10. #endif
  11. namespace CamelotEngine {
  12. Win32GLSupport::Win32GLSupport()
  13. : mInitialWindow(0)
  14. , mHasPixelFormatARB(false)
  15. , mHasMultisample(false)
  16. , mHasHardwareGamma(false)
  17. {
  18. // immediately test WGL_ARB_pixel_format and FSAA support
  19. // so we can set configuration options appropriately
  20. initialiseWGL();
  21. }
  22. template<class C> void remove_duplicates(C& c)
  23. {
  24. std::sort(c.begin(), c.end());
  25. typename C::iterator p = std::unique(c.begin(), c.end());
  26. c.erase(p, c.end());
  27. }
  28. void Win32GLSupport::addConfig()
  29. {
  30. //TODO: EnumDisplayDevices http://msdn.microsoft.com/library/en-us/gdi/devcons_2303.asp
  31. /*vector<string> DisplayDevices;
  32. DISPLAY_DEVICE DisplayDevice;
  33. DisplayDevice.cb = sizeof(DISPLAY_DEVICE);
  34. DWORD i=0;
  35. while (EnumDisplayDevices(NULL, i++, &DisplayDevice, 0) {
  36. DisplayDevices.push_back(DisplayDevice.DeviceName);
  37. }*/
  38. ConfigOption optFullScreen;
  39. ConfigOption optVideoMode;
  40. ConfigOption optColourDepth;
  41. ConfigOption optDisplayFrequency;
  42. ConfigOption optVSync;
  43. ConfigOption optVSyncInterval;
  44. ConfigOption optFSAA;
  45. ConfigOption optRTTMode;
  46. ConfigOption optSRGB;
  47. // FS setting possiblities
  48. optFullScreen.name = "Full Screen";
  49. optFullScreen.possibleValues.push_back("Yes");
  50. optFullScreen.possibleValues.push_back("No");
  51. optFullScreen.currentValue = "Yes";
  52. optFullScreen.immutable = false;
  53. // Video mode possiblities
  54. DEVMODE DevMode;
  55. DevMode.dmSize = sizeof(DEVMODE);
  56. optVideoMode.name = "Video Mode";
  57. optVideoMode.immutable = false;
  58. for (DWORD i = 0; EnumDisplaySettings(NULL, i, &DevMode); ++i)
  59. {
  60. if (DevMode.dmBitsPerPel < 16 || DevMode.dmPelsHeight < 480)
  61. continue;
  62. mDevModes.push_back(DevMode);
  63. StringUtil::StrStreamType str;
  64. str << DevMode.dmPelsWidth << " x " << DevMode.dmPelsHeight;
  65. optVideoMode.possibleValues.push_back(str.str());
  66. }
  67. remove_duplicates(optVideoMode.possibleValues);
  68. optVideoMode.currentValue = optVideoMode.possibleValues.front();
  69. optColourDepth.name = "Colour Depth";
  70. optColourDepth.immutable = false;
  71. optColourDepth.currentValue.clear();
  72. optDisplayFrequency.name = "Display Frequency";
  73. optDisplayFrequency.immutable = false;
  74. optDisplayFrequency.currentValue.clear();
  75. optVSync.name = "VSync";
  76. optVSync.immutable = false;
  77. optVSync.possibleValues.push_back("No");
  78. optVSync.possibleValues.push_back("Yes");
  79. optVSync.currentValue = "No";
  80. optVSyncInterval.name = "VSync Interval";
  81. optVSyncInterval.immutable = false;
  82. optVSyncInterval.possibleValues.push_back( "1" );
  83. optVSyncInterval.possibleValues.push_back( "2" );
  84. optVSyncInterval.possibleValues.push_back( "3" );
  85. optVSyncInterval.possibleValues.push_back( "4" );
  86. optVSyncInterval.currentValue = "1";
  87. optFSAA.name = "FSAA";
  88. optFSAA.immutable = false;
  89. optFSAA.possibleValues.push_back("0");
  90. for (vector<int>::type::iterator it = mFSAALevels.begin(); it != mFSAALevels.end(); ++it)
  91. {
  92. String val = toString(*it);
  93. optFSAA.possibleValues.push_back(val);
  94. /* not implementing CSAA in GL for now
  95. if (*it >= 8)
  96. optFSAA.possibleValues.push_back(val + " [Quality]");
  97. */
  98. }
  99. optFSAA.currentValue = "0";
  100. optRTTMode.name = "RTT Preferred Mode";
  101. optRTTMode.possibleValues.push_back("FBO");
  102. optRTTMode.possibleValues.push_back("PBuffer");
  103. optRTTMode.possibleValues.push_back("Copy");
  104. optRTTMode.currentValue = "FBO";
  105. optRTTMode.immutable = false;
  106. // SRGB on auto window
  107. optSRGB.name = "sRGB Gamma Conversion";
  108. optSRGB.possibleValues.push_back("Yes");
  109. optSRGB.possibleValues.push_back("No");
  110. optSRGB.currentValue = "No";
  111. optSRGB.immutable = false;
  112. mOptions[optFullScreen.name] = optFullScreen;
  113. mOptions[optVideoMode.name] = optVideoMode;
  114. mOptions[optColourDepth.name] = optColourDepth;
  115. mOptions[optDisplayFrequency.name] = optDisplayFrequency;
  116. mOptions[optVSync.name] = optVSync;
  117. mOptions[optVSyncInterval.name] = optVSyncInterval;
  118. mOptions[optFSAA.name] = optFSAA;
  119. mOptions[optRTTMode.name] = optRTTMode;
  120. mOptions[optSRGB.name] = optSRGB;
  121. refreshConfig();
  122. }
  123. void Win32GLSupport::refreshConfig()
  124. {
  125. ConfigOptionMap::iterator optVideoMode = mOptions.find("Video Mode");
  126. ConfigOptionMap::iterator moptColourDepth = mOptions.find("Colour Depth");
  127. ConfigOptionMap::iterator moptDisplayFrequency = mOptions.find("Display Frequency");
  128. if(optVideoMode == mOptions.end() || moptColourDepth == mOptions.end() || moptDisplayFrequency == mOptions.end())
  129. CM_EXCEPT(InvalidParametersException, "Can't find mOptions!");
  130. ConfigOption* optColourDepth = &moptColourDepth->second;
  131. ConfigOption* optDisplayFrequency = &moptDisplayFrequency->second;
  132. const String& val = optVideoMode->second.currentValue;
  133. String::size_type pos = val.find('x');
  134. if (pos == String::npos)
  135. CM_EXCEPT(InvalidParametersException, "Invalid Video Mode provided");
  136. DWORD width = parseUnsignedInt(val.substr(0, pos));
  137. DWORD height = parseUnsignedInt(val.substr(pos+1, String::npos));
  138. for(vector<DEVMODE>::type::const_iterator i = mDevModes.begin(); i != mDevModes.end(); ++i)
  139. {
  140. if (i->dmPelsWidth != width || i->dmPelsHeight != height)
  141. continue;
  142. optColourDepth->possibleValues.push_back(toString((unsigned int)i->dmBitsPerPel));
  143. optDisplayFrequency->possibleValues.push_back(toString((unsigned int)i->dmDisplayFrequency));
  144. }
  145. remove_duplicates(optColourDepth->possibleValues);
  146. remove_duplicates(optDisplayFrequency->possibleValues);
  147. optColourDepth->currentValue = optColourDepth->possibleValues.back();
  148. bool freqValid = std::find(optDisplayFrequency->possibleValues.begin(),
  149. optDisplayFrequency->possibleValues.end(),
  150. optDisplayFrequency->currentValue) != optDisplayFrequency->possibleValues.end();
  151. if ( (optDisplayFrequency->currentValue != "N/A") && !freqValid )
  152. optDisplayFrequency->currentValue = optDisplayFrequency->possibleValues.front();
  153. }
  154. void Win32GLSupport::setConfigOption(const String &name, const String &value)
  155. {
  156. ConfigOptionMap::iterator it = mOptions.find(name);
  157. // Update
  158. if(it != mOptions.end())
  159. it->second.currentValue = value;
  160. else
  161. {
  162. StringUtil::StrStreamType str;
  163. str << "Option named '" << name << "' does not exist.";
  164. CM_EXCEPT(InvalidParametersException, str.str());
  165. }
  166. if( name == "Video Mode" )
  167. refreshConfig();
  168. if( name == "Full Screen" )
  169. {
  170. it = mOptions.find( "Display Frequency" );
  171. if( value == "No" )
  172. {
  173. it->second.currentValue = "N/A";
  174. it->second.immutable = true;
  175. }
  176. else
  177. {
  178. if (it->second.currentValue.empty() || it->second.currentValue == "N/A")
  179. it->second.currentValue = it->second.possibleValues.front();
  180. it->second.immutable = false;
  181. }
  182. }
  183. }
  184. String Win32GLSupport::validateConfig()
  185. {
  186. // TODO, DX9
  187. return StringUtil::BLANK;
  188. }
  189. BOOL CALLBACK Win32GLSupport::sCreateMonitorsInfoEnumProc(
  190. HMONITOR hMonitor, // handle to display monitor
  191. HDC hdcMonitor, // handle to monitor DC
  192. LPRECT lprcMonitor, // monitor intersection rectangle
  193. LPARAM dwData // data
  194. )
  195. {
  196. DisplayMonitorInfoList* pArrMonitorsInfo = (DisplayMonitorInfoList*)dwData;
  197. // Get monitor info
  198. DisplayMonitorInfo displayMonitorInfo;
  199. displayMonitorInfo.hMonitor = hMonitor;
  200. memset(&displayMonitorInfo.monitorInfoEx, 0, sizeof(MONITORINFOEX));
  201. displayMonitorInfo.monitorInfoEx.cbSize = sizeof(MONITORINFOEX);
  202. GetMonitorInfo(hMonitor, &displayMonitorInfo.monitorInfoEx);
  203. pArrMonitorsInfo->push_back(displayMonitorInfo);
  204. return TRUE;
  205. }
  206. RenderWindow* Win32GLSupport::newWindow(const String &name, unsigned int width,
  207. unsigned int height, bool fullScreen, const NameValuePairList *miscParams)
  208. {
  209. Win32Window* window = new Win32Window(*this);
  210. NameValuePairList newParams;
  211. if (miscParams != NULL)
  212. {
  213. newParams = *miscParams;
  214. miscParams = &newParams;
  215. NameValuePairList::const_iterator monitorIndexIt = miscParams->find("monitorIndex");
  216. HMONITOR hMonitor = NULL;
  217. int monitorIndex = -1;
  218. // If monitor index found, try to assign the monitor handle based on it.
  219. if (monitorIndexIt != miscParams->end())
  220. {
  221. if (mMonitorInfoList.empty())
  222. EnumDisplayMonitors(NULL, NULL, sCreateMonitorsInfoEnumProc, (LPARAM)&mMonitorInfoList);
  223. monitorIndex = parseInt(monitorIndexIt->second);
  224. if (monitorIndex < (int)mMonitorInfoList.size())
  225. {
  226. hMonitor = mMonitorInfoList[monitorIndex].hMonitor;
  227. }
  228. }
  229. // If we didn't specified the monitor index, or if it didn't find it
  230. if (hMonitor == NULL)
  231. {
  232. POINT windowAnchorPoint;
  233. NameValuePairList::const_iterator opt;
  234. int left = -1;
  235. int top = -1;
  236. if ((opt = newParams.find("left")) != newParams.end())
  237. left = parseInt(opt->second);
  238. if ((opt = newParams.find("top")) != newParams.end())
  239. top = parseInt(opt->second);
  240. // Fill in anchor point.
  241. windowAnchorPoint.x = left;
  242. windowAnchorPoint.y = top;
  243. // Get the nearest monitor to this window.
  244. hMonitor = MonitorFromPoint(windowAnchorPoint, MONITOR_DEFAULTTONEAREST);
  245. }
  246. newParams["monitorHandle"] = toString((size_t)hMonitor);
  247. }
  248. window->initialize(name, width, height, fullScreen, miscParams);
  249. if(!mInitialWindow)
  250. mInitialWindow = window;
  251. return window;
  252. }
  253. void Win32GLSupport::start()
  254. {
  255. }
  256. void Win32GLSupport::stop()
  257. {
  258. mInitialWindow = 0; // Since there is no removeWindow, although there should be...
  259. }
  260. void Win32GLSupport::initialiseExtensions()
  261. {
  262. assert(mInitialWindow);
  263. // First, initialise the normal extensions
  264. GLSupport::initialiseExtensions();
  265. // wglew init
  266. #if CM_THREAD_SUPPORT != 1
  267. wglewContextInit(this);
  268. #endif
  269. // Check for W32 specific extensions probe function
  270. PFNWGLGETEXTENSIONSSTRINGARBPROC _wglGetExtensionsStringARB =
  271. (PFNWGLGETEXTENSIONSSTRINGARBPROC)wglGetProcAddress("wglGetExtensionsStringARB");
  272. if(!_wglGetExtensionsStringARB)
  273. return;
  274. const char *wgl_extensions = _wglGetExtensionsStringARB(mInitialWindow->getHDC());
  275. // Parse them, and add them to the main list
  276. StringStream ext;
  277. String instr;
  278. ext << wgl_extensions;
  279. while(ext >> instr)
  280. {
  281. extensionList.insert(instr);
  282. }
  283. }
  284. void* Win32GLSupport::getProcAddress(const String& procname)
  285. {
  286. return (void*)wglGetProcAddress( procname.c_str() );
  287. }
  288. void Win32GLSupport::initialiseWGL()
  289. {
  290. // wglGetProcAddress does not work without an active OpenGL context,
  291. // but we need wglChoosePixelFormatARB's address before we can
  292. // create our main window. Thank you very much, Microsoft!
  293. //
  294. // The solution is to create a dummy OpenGL window first, and then
  295. // test for WGL_ARB_pixel_format support. If it is not supported,
  296. // we make sure to never call the ARB pixel format functions.
  297. //
  298. // If is is supported, we call the pixel format functions at least once
  299. // to initialise them (pointers are stored by glprocs.h). We can also
  300. // take this opportunity to enumerate the valid FSAA modes.
  301. LPCSTR dummyText = "OgreWglDummy";
  302. #ifdef CM_STATIC_LIB
  303. HINSTANCE hinst = GetModuleHandle( NULL );
  304. #else
  305. # if CM_DEBUG_MODE == 1
  306. HINSTANCE hinst = GetModuleHandle("RenderSystem_GL_d.dll");
  307. # else
  308. HINSTANCE hinst = GetModuleHandle("RenderSystem_GL.dll");
  309. # endif
  310. #endif
  311. WNDCLASS dummyClass;
  312. memset(&dummyClass, 0, sizeof(WNDCLASS));
  313. dummyClass.style = CS_OWNDC;
  314. dummyClass.hInstance = hinst;
  315. dummyClass.lpfnWndProc = dummyWndProc;
  316. dummyClass.lpszClassName = dummyText;
  317. RegisterClass(&dummyClass);
  318. HWND hwnd = CreateWindow(dummyText, dummyText,
  319. WS_POPUP | WS_CLIPCHILDREN,
  320. 0, 0, 32, 32, 0, 0, hinst, 0);
  321. // if a simple CreateWindow fails, then boy are we in trouble...
  322. if (hwnd == NULL)
  323. CM_EXCEPT(RenderingAPIException, "CreateWindow() failed");
  324. // no chance of failure and no need to release thanks to CS_OWNDC
  325. HDC hdc = GetDC(hwnd);
  326. // assign a simple OpenGL pixel format that everyone supports
  327. PIXELFORMATDESCRIPTOR pfd;
  328. memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
  329. pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
  330. pfd.nVersion = 1;
  331. pfd.cColorBits = 16;
  332. pfd.cDepthBits = 15;
  333. pfd.dwFlags = PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_DOUBLEBUFFER;
  334. pfd.iPixelType = PFD_TYPE_RGBA;
  335. // if these fail, wglCreateContext will also quietly fail
  336. int format;
  337. if ((format = ChoosePixelFormat(hdc, &pfd)) != 0)
  338. SetPixelFormat(hdc, format, &pfd);
  339. HGLRC hrc = wglCreateContext(hdc);
  340. if (hrc)
  341. {
  342. HGLRC oldrc = wglGetCurrentContext();
  343. HDC oldhdc = wglGetCurrentDC();
  344. // if wglMakeCurrent fails, wglGetProcAddress will return null
  345. wglMakeCurrent(hdc, hrc);
  346. PFNWGLGETEXTENSIONSSTRINGARBPROC _wglGetExtensionsStringARB =
  347. (PFNWGLGETEXTENSIONSSTRINGARBPROC)
  348. wglGetProcAddress("wglGetExtensionsStringARB");
  349. // check for pixel format and multisampling support
  350. if (_wglGetExtensionsStringARB)
  351. {
  352. std::istringstream wglexts(_wglGetExtensionsStringARB(hdc));
  353. std::string ext;
  354. while (wglexts >> ext)
  355. {
  356. if (ext == "WGL_ARB_pixel_format")
  357. mHasPixelFormatARB = true;
  358. else if (ext == "WGL_ARB_multisample")
  359. mHasMultisample = true;
  360. else if (ext == "WGL_EXT_framebuffer_sRGB")
  361. mHasHardwareGamma = true;
  362. }
  363. }
  364. if (mHasPixelFormatARB && mHasMultisample)
  365. {
  366. // enumerate all formats w/ multisampling
  367. static const int iattr[] = {
  368. WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
  369. WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
  370. WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
  371. WGL_SAMPLE_BUFFERS_ARB, GL_TRUE,
  372. WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
  373. /* We are no matter about the colour, depth and stencil buffers here
  374. WGL_COLOR_BITS_ARB, 24,
  375. WGL_ALPHA_BITS_ARB, 8,
  376. WGL_DEPTH_BITS_ARB, 24,
  377. WGL_STENCIL_BITS_ARB, 8,
  378. */
  379. WGL_SAMPLES_ARB, 2,
  380. 0
  381. };
  382. int formats[256];
  383. unsigned int count;
  384. // cheating here. wglChoosePixelFormatARB procc address needed later on
  385. // when a valid GL context does not exist and glew is not initialized yet.
  386. WGLEW_GET_FUN(__wglewChoosePixelFormatARB) =
  387. (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB");
  388. if (WGLEW_GET_FUN(__wglewChoosePixelFormatARB)(hdc, iattr, 0, 256, formats, &count))
  389. {
  390. // determine what multisampling levels are offered
  391. int query = WGL_SAMPLES_ARB, samples;
  392. for (unsigned int i = 0; i < count; ++i)
  393. {
  394. PFNWGLGETPIXELFORMATATTRIBIVARBPROC _wglGetPixelFormatAttribivARB =
  395. (PFNWGLGETPIXELFORMATATTRIBIVARBPROC)
  396. wglGetProcAddress("wglGetPixelFormatAttribivARB");
  397. if (_wglGetPixelFormatAttribivARB(hdc, formats[i], 0, 1, &query, &samples))
  398. {
  399. mFSAALevels.push_back(samples);
  400. }
  401. }
  402. remove_duplicates(mFSAALevels);
  403. }
  404. }
  405. wglMakeCurrent(oldhdc, oldrc);
  406. wglDeleteContext(hrc);
  407. }
  408. // clean up our dummy window and class
  409. DestroyWindow(hwnd);
  410. UnregisterClass(dummyText, hinst);
  411. }
  412. LRESULT Win32GLSupport::dummyWndProc(HWND hwnd, UINT umsg, WPARAM wp, LPARAM lp)
  413. {
  414. return DefWindowProc(hwnd, umsg, wp, lp);
  415. }
  416. bool Win32GLSupport::selectPixelFormat(HDC hdc, int colourDepth, int multisample, bool hwGamma)
  417. {
  418. PIXELFORMATDESCRIPTOR pfd;
  419. memset(&pfd, 0, sizeof(pfd));
  420. pfd.nSize = sizeof(pfd);
  421. pfd.nVersion = 1;
  422. pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
  423. pfd.iPixelType = PFD_TYPE_RGBA;
  424. pfd.cColorBits = (colourDepth > 16)? 24 : colourDepth;
  425. pfd.cAlphaBits = (colourDepth > 16)? 8 : 0;
  426. pfd.cDepthBits = 24;
  427. pfd.cStencilBits = 8;
  428. int format = 0;
  429. int useHwGamma = hwGamma? GL_TRUE : GL_FALSE;
  430. if (multisample && (!mHasMultisample || !mHasPixelFormatARB))
  431. return false;
  432. if (hwGamma && !mHasHardwareGamma)
  433. return false;
  434. if ((multisample || hwGamma) && WGLEW_GET_FUN(__wglewChoosePixelFormatARB))
  435. {
  436. // Use WGL to test extended caps (multisample, sRGB)
  437. vector<int>::type attribList;
  438. attribList.push_back(WGL_DRAW_TO_WINDOW_ARB); attribList.push_back(GL_TRUE);
  439. attribList.push_back(WGL_SUPPORT_OPENGL_ARB); attribList.push_back(GL_TRUE);
  440. attribList.push_back(WGL_DOUBLE_BUFFER_ARB); attribList.push_back(GL_TRUE);
  441. attribList.push_back(WGL_SAMPLE_BUFFERS_ARB); attribList.push_back(GL_TRUE);
  442. attribList.push_back(WGL_ACCELERATION_ARB); attribList.push_back(WGL_FULL_ACCELERATION_ARB);
  443. attribList.push_back(WGL_COLOR_BITS_ARB); attribList.push_back(pfd.cColorBits);
  444. attribList.push_back(WGL_ALPHA_BITS_ARB); attribList.push_back(pfd.cAlphaBits);
  445. attribList.push_back(WGL_DEPTH_BITS_ARB); attribList.push_back(24);
  446. attribList.push_back(WGL_STENCIL_BITS_ARB); attribList.push_back(8);
  447. attribList.push_back(WGL_SAMPLES_ARB); attribList.push_back(multisample);
  448. if (useHwGamma && checkExtension("WGL_EXT_framebuffer_sRGB"))
  449. {
  450. attribList.push_back(WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT); attribList.push_back(GL_TRUE);
  451. }
  452. // terminator
  453. attribList.push_back(0);
  454. UINT nformats;
  455. // ChoosePixelFormatARB proc address was obtained when setting up a dummy GL context in initialiseWGL()
  456. // since glew hasn't been initialized yet, we have to cheat and use the previously obtained address
  457. if (!WGLEW_GET_FUN(__wglewChoosePixelFormatARB)(hdc, &(attribList[0]), NULL, 1, &format, &nformats) || nformats <= 0)
  458. return false;
  459. }
  460. else
  461. {
  462. format = ChoosePixelFormat(hdc, &pfd);
  463. }
  464. return (format && SetPixelFormat(hdc, format, &pfd));
  465. }
  466. bool Win32GLSupport::supportsPBuffers()
  467. {
  468. return WGLEW_GET_FUN(__WGLEW_ARB_pbuffer) != GL_FALSE;
  469. }
  470. unsigned int Win32GLSupport::getDisplayMonitorCount() const
  471. {
  472. if (mMonitorInfoList.empty())
  473. EnumDisplayMonitors(NULL, NULL, sCreateMonitorsInfoEnumProc, (LPARAM)&mMonitorInfoList);
  474. return (unsigned int)mMonitorInfoList.size();
  475. }
  476. String translateWGLError()
  477. {
  478. int winError = GetLastError();
  479. char* errDesc;
  480. int i;
  481. errDesc = new char[255];
  482. // Try windows errors first
  483. i = FormatMessage(
  484. FORMAT_MESSAGE_FROM_SYSTEM |
  485. FORMAT_MESSAGE_IGNORE_INSERTS,
  486. NULL,
  487. winError,
  488. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  489. (LPTSTR) errDesc,
  490. 255,
  491. NULL
  492. );
  493. return String(errDesc);
  494. }
  495. }