CmWin32GLSupport.cpp 23 KB

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