gfxGLDevice.win.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  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. #include "platformWin32/platformWin32.h"
  23. #include "gfx/gfxCubemap.h"
  24. #include "gfx/screenshot.h"
  25. #include "gfx/GL/gfxGLDevice.h"
  26. #include "gfx/GL/gfxGLEnumTranslate.h"
  27. #include "gfx/GL/gfxGLVertexBuffer.h"
  28. #include "gfx/GL/gfxGLPrimitiveBuffer.h"
  29. #include "gfx/gl/gfxGLTextureTarget.h"
  30. #include "gfx/GL/gfxGLWindowTarget.h"
  31. #include "gfx/GL/gfxGLTextureManager.h"
  32. #include "gfx/GL/gfxGLTextureObject.h"
  33. #include "gfx/GL/gfxGLCubemap.h"
  34. #include "gfx/GL/gfxGLCardProfiler.h"
  35. #include "windowManager/win32/win32Window.h"
  36. #include "ggl/Win32/wgl.h"
  37. #define GETHWND(x) static_cast<Win32Window*>(x)->getHWND()
  38. // yonked from winWindow.cc
  39. void CreatePixelFormat( PIXELFORMATDESCRIPTOR *pPFD, S32 colorBits, S32 depthBits, S32 stencilBits, bool stereo )
  40. {
  41. PIXELFORMATDESCRIPTOR src =
  42. {
  43. sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd
  44. 1, // version number
  45. PFD_DRAW_TO_WINDOW | // support window
  46. PFD_SUPPORT_OPENGL | // support OpenGL
  47. PFD_DOUBLEBUFFER, // double buffered
  48. PFD_TYPE_RGBA, // RGBA type
  49. colorBits, // color depth
  50. 0, 0, 0, 0, 0, 0, // color bits ignored
  51. 0, // no alpha buffer
  52. 0, // shift bit ignored
  53. 0, // no accumulation buffer
  54. 0, 0, 0, 0, // accum bits ignored
  55. depthBits, // z-buffer
  56. stencilBits, // stencil buffer
  57. 0, // no auxiliary buffer
  58. PFD_MAIN_PLANE, // main layer
  59. 0, // reserved
  60. 0, 0, 0 // layer masks ignored
  61. };
  62. if ( stereo )
  63. {
  64. //ri.Printf( PRINT_ALL, "...attempting to use stereo\n" );
  65. src.dwFlags |= PFD_STEREO;
  66. //glConfig.stereoEnabled = true;
  67. }
  68. else
  69. {
  70. //glConfig.stereoEnabled = qfalse;
  71. }
  72. *pPFD = src;
  73. }
  74. extern void loadGLCore();
  75. extern void loadGLExtensions(void* context);
  76. void GFXGLDevice::enumerateAdapters( Vector<GFXAdapter*> &adapterList )
  77. {
  78. // GL_ERROR_CHECK();
  79. WNDCLASS windowclass;
  80. dMemset( &windowclass, 0, sizeof( WNDCLASS ) );
  81. windowclass.lpszClassName = L"GFX-OpenGL";
  82. windowclass.style = CS_OWNDC;
  83. windowclass.lpfnWndProc = DefWindowProc;
  84. windowclass.hInstance = winState.appInstance;
  85. if( !RegisterClass( &windowclass ) )
  86. AssertFatal( false, "Failed to register the window class for the GL test window." );
  87. // Now create a window
  88. HWND hwnd = CreateWindow( L"GFX-OpenGL", L"", WS_POPUP, 0, 0, 640, 480,
  89. NULL, NULL, winState.appInstance, NULL );
  90. AssertFatal( hwnd != NULL, "Failed to create the window for the GL test window." );
  91. // Create a device context
  92. HDC tempDC = GetDC( hwnd );
  93. AssertFatal( tempDC != NULL, "Failed to create device context" );
  94. // Create pixel format descriptor...
  95. PIXELFORMATDESCRIPTOR pfd;
  96. CreatePixelFormat( &pfd, 16, 16, 8, false ); // 16 bit color, 16 bit depth, 8 bit stencil...everyone can do this
  97. if( !SetPixelFormat( tempDC, ChoosePixelFormat( tempDC, &pfd ), &pfd ) )
  98. AssertFatal( false, "I don't know who's responcible for this, but I want caught..." );
  99. // Create a rendering context!
  100. HGLRC tempGLRC = wglCreateContext( tempDC );
  101. if( !wglMakeCurrent( tempDC, tempGLRC ) )
  102. AssertFatal( false, "I want them caught and killed." );
  103. // Add the GL renderer
  104. loadGLCore();
  105. loadGLExtensions(tempDC);
  106. GFXAdapter *toAdd = new GFXAdapter;
  107. toAdd->mIndex = 0;
  108. const char* renderer = (const char*) glGetString( GL_RENDERER );
  109. AssertFatal( renderer != NULL, "GL_RENDERER returned NULL!" );
  110. if (renderer)
  111. {
  112. dStrcpy(toAdd->mName, renderer);
  113. dStrncat(toAdd->mName, " OpenGL", GFXAdapter::MaxAdapterNameLen);
  114. }
  115. else
  116. dStrcpy(toAdd->mName, "OpenGL");
  117. toAdd->mType = OpenGL;
  118. toAdd->mShaderModel = 0.f;
  119. toAdd->mCreateDeviceInstanceDelegate = mCreateDeviceInstance;
  120. // Enumerate all available resolutions:
  121. DEVMODE devMode;
  122. U32 modeNum = 0;
  123. U32 stillGoing = true;
  124. while ( stillGoing )
  125. {
  126. dMemset( &devMode, 0, sizeof( devMode ) );
  127. devMode.dmSize = sizeof( devMode );
  128. stillGoing = EnumDisplaySettings( NULL, modeNum++, &devMode );
  129. if (( devMode.dmPelsWidth >= 480) && (devMode.dmPelsHeight >= 360 )
  130. && ( devMode.dmBitsPerPel == 16 || devMode.dmBitsPerPel == 32 ))
  131. {
  132. GFXVideoMode vmAdd;
  133. vmAdd.bitDepth = devMode.dmBitsPerPel;
  134. vmAdd.fullScreen = true;
  135. vmAdd.refreshRate = devMode.dmDisplayFrequency;
  136. vmAdd.resolution.x = devMode.dmPelsWidth;
  137. vmAdd.resolution.y = devMode.dmPelsHeight;
  138. // Only add this resolution if it is not already in the list:
  139. bool alreadyInList = false;
  140. for (Vector<GFXVideoMode>::iterator i = toAdd->mAvailableModes.begin(); i != toAdd->mAvailableModes.end(); i++)
  141. {
  142. if (vmAdd == *i)
  143. {
  144. alreadyInList = true;
  145. break;
  146. }
  147. }
  148. if(alreadyInList)
  149. continue;
  150. toAdd->mAvailableModes.push_back( vmAdd );
  151. }
  152. }
  153. // Add to the list of available adapters.
  154. adapterList.push_back(toAdd);
  155. // Cleanup our window
  156. wglMakeCurrent(NULL, NULL);
  157. wglDeleteContext(tempGLRC);
  158. ReleaseDC(hwnd, tempDC);
  159. DestroyWindow(hwnd);
  160. UnregisterClass(L"GFX-OpenGL", winState.appInstance);
  161. }
  162. void GFXGLDevice::enumerateVideoModes()
  163. {
  164. mVideoModes.clear();
  165. // Enumerate all available resolutions:
  166. DEVMODE devMode;
  167. U32 modeNum = 0;
  168. U32 stillGoing = true;
  169. while ( stillGoing )
  170. {
  171. dMemset( &devMode, 0, sizeof( devMode ) );
  172. devMode.dmSize = sizeof( devMode );
  173. stillGoing = EnumDisplaySettings( NULL, modeNum++, &devMode );
  174. if (( devMode.dmPelsWidth >= 480) && (devMode.dmPelsHeight >= 360 )
  175. && ( devMode.dmBitsPerPel == 16 || devMode.dmBitsPerPel == 32 ))
  176. //( smCanSwitchBitDepth || devMode.dmBitsPerPel == winState.desktopBitsPixel ) )
  177. {
  178. GFXVideoMode toAdd;
  179. toAdd.bitDepth = devMode.dmBitsPerPel;
  180. toAdd.fullScreen = false;
  181. toAdd.refreshRate = devMode.dmDisplayFrequency;
  182. toAdd.resolution.x = devMode.dmPelsWidth;
  183. toAdd.resolution.y = devMode.dmPelsHeight;
  184. // Only add this resolution if it is not already in the list:
  185. bool alreadyInList = false;
  186. for (Vector<GFXVideoMode>::iterator i = mVideoModes.begin(); i != mVideoModes.end(); i++)
  187. {
  188. if (toAdd == *i)
  189. {
  190. alreadyInList = true;
  191. break;
  192. }
  193. }
  194. if ( !alreadyInList )
  195. {
  196. //Con::printf("Resolution: %dx%d %d bpp %d Refresh rate: %d", toAdd.resolution.x, toAdd.resolution.y, toAdd.bitDepth, toAdd.refreshRate);
  197. mVideoModes.push_back( toAdd );
  198. }
  199. }
  200. }
  201. }
  202. void GFXGLDevice::init( const GFXVideoMode &mode, PlatformWindow *window )
  203. {
  204. AssertFatal(window, "GFXGLDevice::init - no window specified, can't init device without a window!");
  205. AssertFatal(dynamic_cast<Win32Window*>(window), "Invalid window class type!");
  206. HWND hwnd = GETHWND(window);
  207. RECT rect;
  208. GetClientRect(hwnd, &rect);
  209. Point2I resolution;
  210. resolution.x = rect.right - rect.left;
  211. resolution.y = rect.bottom - rect.top;
  212. // Create a device context
  213. HDC hdcGL = GetDC( hwnd );
  214. AssertFatal( hdcGL != NULL, "Failed to create device context" );
  215. // Create pixel format descriptor...
  216. PIXELFORMATDESCRIPTOR pfd;
  217. CreatePixelFormat( &pfd, 16, 16, 8, false ); // 16 bit color, 16 bit depth, 8 bit stencil...everyone can do this
  218. if( !SetPixelFormat( hdcGL, ChoosePixelFormat( hdcGL, &pfd ), &pfd ) )
  219. {
  220. AssertFatal( false, "GFXGLDevice::init - cannot get the one and only pixel format we check for." );
  221. }
  222. // Create a rendering context!
  223. mContext = wglCreateContext( hdcGL );
  224. if( !wglMakeCurrent( hdcGL, (HGLRC)mContext ) )
  225. AssertFatal( false , "GFXGLDevice::init - cannot make our context current. Or maybe we can't create it." );
  226. loadGLCore();
  227. loadGLExtensions(hdcGL);
  228. wglSwapIntervalEXT(0);
  229. // It is very important that extensions be loaded
  230. // before we call initGLState()
  231. initGLState();
  232. mProjectionMatrix.identity();
  233. mInitialized = true;
  234. deviceInited();
  235. }
  236. bool GFXGLDevice::beginSceneInternal()
  237. {
  238. glGetError();
  239. return true;
  240. }
  241. U32 GFXGLDevice::getTotalVideoMemory()
  242. {
  243. // CodeReview [ags 12/21/07] Figure out how to do this.
  244. return 0;
  245. }
  246. //------------------------------------------------------------------------------
  247. GFXWindowTarget *GFXGLDevice::allocWindowTarget( PlatformWindow *window )
  248. {
  249. HDC hdcGL = GetDC(GETHWND(window));
  250. if(!mContext)
  251. {
  252. init(window->getVideoMode(), window);
  253. GFXGLWindowTarget *ggwt = new GFXGLWindowTarget(window, this);
  254. ggwt->registerResourceWithDevice(this);
  255. ggwt->mContext = wglCreateContext(hdcGL);
  256. AssertFatal(ggwt->mContext, "GFXGLDevice::allocWindowTarget - failed to allocate window target!");
  257. return ggwt;
  258. }
  259. GFXGLWindowTarget *ggwt = new GFXGLWindowTarget(window, this);
  260. ggwt->registerResourceWithDevice(this);
  261. // Create pixel format descriptor...
  262. PIXELFORMATDESCRIPTOR pfd;
  263. CreatePixelFormat( &pfd, 16, 16, 8, false ); // 16 bit color, 16 bit depth, 8 bit stencil...everyone can do this
  264. if( !SetPixelFormat( hdcGL, ChoosePixelFormat( hdcGL, &pfd ), &pfd ) )
  265. {
  266. AssertFatal( false, "GFXGLDevice::allocWindowTarget - cannot get the one and only pixel format we check for." );
  267. }
  268. ggwt->mContext = wglCreateContext(hdcGL);
  269. DWORD w = GetLastError();
  270. AssertFatal(ggwt->mContext, "GFXGLDevice::allocWindowTarget - failed to allocate window target!");
  271. wglMakeCurrent(NULL, NULL);
  272. bool res = wglShareLists((HGLRC)mContext, (HGLRC)ggwt->mContext);
  273. w = GetLastError();
  274. wglMakeCurrent(hdcGL, (HGLRC)ggwt->mContext);
  275. AssertFatal(res, "GFXGLDevice::allocWindowTarget - wasn't able to share contexts!");
  276. return ggwt;
  277. }
  278. void GFXGLDevice::_updateRenderTargets()
  279. {
  280. if ( mRTDirty || mCurrentRT->isPendingState() )
  281. {
  282. // GL doesn't need to deactivate targets.
  283. mRTDeactivate = NULL;
  284. // NOTE: The render target changes is not really accurate
  285. // as the GFXTextureTarget supports MRT internally. So when
  286. // we activate a GFXTarget it could result in multiple calls
  287. // to SetRenderTarget on the actual device.
  288. mDeviceStatistics.mRenderTargetChanges++;
  289. GFXGLTextureTarget *tex = dynamic_cast<GFXGLTextureTarget*>( mCurrentRT.getPointer() );
  290. if ( tex )
  291. {
  292. tex->applyState();
  293. tex->makeActive();
  294. }
  295. else
  296. {
  297. GFXGLWindowTarget *win = dynamic_cast<GFXGLWindowTarget*>( mCurrentRT.getPointer() );
  298. AssertFatal( win != NULL,
  299. "GFXGLDevice::_updateRenderTargets() - invalid target subclass passed!" );
  300. //DWORD w1 = GetLastError();
  301. HWND hwnd = GETHWND(win->getWindow());
  302. HDC winDc = GetDC(hwnd);
  303. bool res = wglMakeCurrent(winDc,(HGLRC)win->mContext);
  304. //DWORD w2 = GetLastError();
  305. AssertFatal(res==true,"GFXGLDevice::setActiveRenderTarget - failed");
  306. }
  307. mRTDirty = false;
  308. }
  309. if ( mViewportDirty )
  310. {
  311. glViewport( mViewport.point.x, mViewport.point.y, mViewport.extent.x, mViewport.extent.y );
  312. mViewportDirty = false;
  313. }
  314. }
  315. GFXFence* GFXGLDevice::_createPlatformSpecificFence()
  316. {
  317. return NULL;
  318. }
  319. //-----------------------------------------------------------------------------
  320. void GFXGLWindowTarget::makeActive()
  321. {
  322. }
  323. bool GFXGLWindowTarget::present()
  324. {
  325. HWND hwnd = GETHWND(getWindow());
  326. SwapBuffers(GetDC(hwnd));
  327. return true;
  328. }
  329. void GFXGLWindowTarget::_teardownCurrentMode()
  330. {
  331. }
  332. void GFXGLWindowTarget::_setupNewMode()
  333. {
  334. }