ViewPort.cpp 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  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/ViewPort.h>
  14. #include <Engine/Graphics/GfxProfile.h>
  15. #include <Engine/Graphics/GfxLibrary.h>
  16. #include <Engine/Base/Statistics_internal.h>
  17. extern INDEX ogl_bExclusive;
  18. // helper for D3D surface
  19. #ifdef SE1_D3D
  20. static void CreateSwapChain_D3D( CViewPort *pvp, PIX pixSizeI, PIX pixSizeJ)
  21. {
  22. HRESULT hr;
  23. D3DPRESENT_PARAMETERS d3dPresentParams;
  24. memset( &d3dPresentParams, 0, sizeof(d3dPresentParams));
  25. d3dPresentParams.Windowed = TRUE;
  26. d3dPresentParams.BackBufferWidth = pixSizeI;
  27. d3dPresentParams.BackBufferHeight = pixSizeJ;
  28. d3dPresentParams.BackBufferFormat = _pGfx->gl_d3dColorFormat;
  29. d3dPresentParams.BackBufferCount = 1;
  30. d3dPresentParams.MultiSampleType = D3DMULTISAMPLE_NONE; // !!!! TODO
  31. d3dPresentParams.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
  32. d3dPresentParams.SwapEffect = D3DSWAPEFFECT_DISCARD;
  33. d3dPresentParams.hDeviceWindow = pvp->vp_hWnd;
  34. ASSERT( pvp->vp_pSwapChain==NULL && pvp->vp_pSurfDepth==NULL);
  35. hr = _pGfx->gl_pd3dDevice->CreateAdditionalSwapChain( &d3dPresentParams, &pvp->vp_pSwapChain);
  36. D3D_CHECKERROR(hr);
  37. hr = _pGfx->gl_pd3dDevice->CreateDepthStencilSurface( pixSizeI, pixSizeJ, _pGfx->gl_d3dDepthFormat,
  38. D3DMULTISAMPLE_NONE, &pvp->vp_pSurfDepth);
  39. D3D_CHECKERROR(hr);
  40. ASSERT( pvp->vp_pSwapChain!=NULL);
  41. ASSERT( pvp->vp_pSurfDepth!=NULL);
  42. }
  43. static void SetAsRenderTarget_D3D( CViewPort *pvp)
  44. {
  45. HRESULT hr;
  46. LPDIRECT3DSURFACE8 pColorSurface;
  47. hr = pvp->vp_pSwapChain->GetBackBuffer( 0, D3DBACKBUFFER_TYPE_MONO, &pColorSurface);
  48. D3D_CHECKERROR(hr);
  49. hr = _pGfx->gl_pd3dDevice->SetRenderTarget( pColorSurface, pvp->vp_pSurfDepth);
  50. D3D_CHECKERROR(hr);
  51. D3DRELEASE( pColorSurface, TRUE);
  52. }
  53. #endif // SE1_D3D
  54. // helper for OGL
  55. CTempDC::CTempDC(HWND hWnd)
  56. {
  57. ASSERT(hWnd!=NULL);
  58. hwnd = hWnd;
  59. hdc = GetDC(hwnd);
  60. ASSERT(hdc!=NULL);
  61. }
  62. CTempDC::~CTempDC(void)
  63. {
  64. ReleaseDC(hwnd, hdc);
  65. }
  66. /*
  67. * ViewPort functions
  68. */
  69. CViewPort::CViewPort( PIX pixWidth, PIX pixHeight, HWND hWnd) :
  70. vp_Raster( pixWidth, pixHeight, 0)
  71. {
  72. vp_hWnd = NULL;
  73. vp_hWndParent = hWnd;
  74. #ifdef SE1_D3D
  75. vp_pSwapChain = NULL;
  76. vp_pSurfDepth = NULL;
  77. #endif // SE1_D3D
  78. vp_ctDisplayChanges = 0;
  79. OpenCanvas();
  80. vp_Raster.ra_pvpViewPort = this;
  81. }
  82. CViewPort::~CViewPort(void)
  83. {
  84. CloseCanvas(TRUE);
  85. // reset current viewport if needed
  86. if( _pGfx->gl_pvpActive==this) _pGfx->gl_pvpActive = NULL;
  87. }
  88. #define CViewPortCLASS "ViewPort Window"
  89. static BOOL _bClassRegistered = FALSE;
  90. LRESULT CALLBACK CViewPortCLASS_WindowProc(
  91. HWND hWnd, // handle to window
  92. UINT Msg, // message identifier
  93. WPARAM wParam, // first message parameter
  94. LPARAM lParam // second message parameter
  95. )
  96. {
  97. // forget erase bacground messages
  98. if (Msg==WM_ERASEBKGND) return TRUE;
  99. // if any mouse message
  100. if ((Msg>=WM_MOUSEFIRST&&Msg<=WM_MOUSELAST)) {
  101. // send it to parent
  102. HWND hWndParent = GetParent(hWnd);
  103. ASSERT(hWndParent!=NULL);
  104. return CallWindowProc( (WNDPROC)GetWindowLong(hWndParent, GWL_WNDPROC),
  105. hWndParent, Msg, wParam, lParam);
  106. }
  107. return DefWindowProc(hWnd, Msg, wParam, lParam);
  108. }
  109. // open overlaid window for rendering context
  110. void CViewPort::OpenCanvas(void)
  111. {
  112. // do nothing if not feasable
  113. if( vp_hWnd!=NULL || vp_hWndParent==NULL) return;
  114. // register class
  115. if( !_bClassRegistered) {
  116. WNDCLASSA wc;
  117. wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
  118. wc.lpfnWndProc = CViewPortCLASS_WindowProc;
  119. wc.cbClsExtra = 0;
  120. wc.cbWndExtra = 0;
  121. wc.hInstance = NULL;
  122. wc.hIcon = NULL;
  123. wc.hCursor = LoadCursor( NULL, IDC_ARROW);
  124. wc.hbrBackground = NULL;
  125. wc.lpszMenuName = NULL;
  126. wc.lpszClassName = CViewPortCLASS;
  127. RegisterClassA(&wc);
  128. _bClassRegistered = TRUE;
  129. }
  130. // determine window and desktopsize
  131. RECT rectWindow;
  132. GetClientRect( vp_hWndParent, &rectWindow);
  133. const PIX pixWinSizeI = rectWindow.right - rectWindow.left;
  134. const PIX pixWinSizeJ = rectWindow.bottom - rectWindow.top;
  135. CDisplayMode dm;
  136. _pGfx->GetCurrentDisplayMode(dm);
  137. ASSERT( (dm.dm_pixSizeI==0 && dm.dm_pixSizeJ==0) || (dm.dm_pixSizeI!=0 && dm.dm_pixSizeJ!=0));
  138. const BOOL bFullScreen = (dm.dm_pixSizeI==pixWinSizeI && dm.dm_pixSizeJ==pixWinSizeJ);
  139. // set fullscreen attribs if window size is equal to screen size
  140. DWORD dwExStyle = NONE;
  141. DWORD dwStyle = WS_CHILD|WS_CLIPCHILDREN|WS_CLIPSIBLINGS;
  142. if( bFullScreen && ogl_bExclusive) {
  143. dwExStyle = WS_EX_TOPMOST;
  144. dwStyle = WS_POPUP;
  145. }
  146. // set child window
  147. vp_hWnd = ::CreateWindowExA(
  148. dwExStyle,
  149. CViewPortCLASS,
  150. "", // title
  151. dwStyle,
  152. 0,0,
  153. 0,0, // window size
  154. vp_hWndParent,
  155. NULL,
  156. (HINSTANCE)GetWindowLong(vp_hWndParent, GWL_HINSTANCE),
  157. NULL);
  158. ASSERT( vp_hWnd!=NULL);
  159. #ifdef SE1_D3D
  160. // prepare new swap chain for D3D
  161. if( _pGfx->gl_eCurrentAPI==GAT_D3D && !bFullScreen) CreateSwapChain_D3D( this, pixWinSizeI, pixWinSizeJ);
  162. #endif // SE1_D3D
  163. // resize raster
  164. Resize();
  165. ShowWindow( vp_hWnd, SW_SHOW);
  166. #ifdef SE1_D3D
  167. // set as rendering target
  168. if( _pGfx->gl_eCurrentAPI==GAT_D3D && vp_pSwapChain!=NULL) SetAsRenderTarget_D3D(this);
  169. #endif // SE1_D3D
  170. }
  171. // close overlaid window
  172. void CViewPort::CloseCanvas( BOOL bRelease/*=FALSE*/)
  173. {
  174. // release D3D swap chain if allocated
  175. #ifdef SE1_D3D
  176. if( _pGfx->gl_eCurrentAPI==GAT_D3D && bRelease) {
  177. if( vp_pSwapChain!=NULL) D3DRELEASE( vp_pSwapChain, TRUE);
  178. if( vp_pSurfDepth!=NULL) D3DRELEASE( vp_pSurfDepth, TRUE);
  179. }
  180. #endif // SE1_D3D
  181. // destroy window
  182. if( vp_hWnd!=NULL && IsWindow(vp_hWnd)) {
  183. BOOL bRes = DestroyWindow(vp_hWnd);
  184. ASSERT(bRes);
  185. }
  186. // mark
  187. vp_hWnd = NULL;
  188. #ifdef SE1_D3D
  189. vp_pSwapChain = NULL;
  190. vp_pSurfDepth = NULL;
  191. #endif // SE1_D3D
  192. }
  193. // Change size of this viewport, it's raster and all it's drawports
  194. void CViewPort::Resize(void)
  195. {
  196. PIX pixNewWidth, pixNewHeight;
  197. RECT rectWindow;
  198. // get the size of the window
  199. GetClientRect( vp_hWndParent, &rectWindow);
  200. pixNewWidth = rectWindow.right - rectWindow.left;
  201. pixNewHeight = rectWindow.bottom - rectWindow.top;
  202. // resize child window
  203. ASSERT( vp_hWnd!=NULL);
  204. SetWindowPos( vp_hWnd, NULL, 0,0, pixNewWidth, pixNewHeight, SWP_NOZORDER|SWP_NOMOVE);
  205. // resize the raster
  206. vp_Raster.Resize( pixNewWidth, pixNewHeight);
  207. // "resize" D3D surface (if any)
  208. #ifdef SE1_D3D
  209. if( _pGfx->gl_eCurrentAPI==GAT_D3D && vp_pSwapChain!=NULL) {
  210. // release old surface
  211. ASSERT( vp_pSurfDepth!=NULL);
  212. D3DRELEASE( vp_pSwapChain, TRUE);
  213. D3DRELEASE( vp_pSurfDepth, TRUE);
  214. // create a new one and set it as current
  215. CreateSwapChain_D3D( this, pixNewWidth, pixNewHeight);
  216. SetAsRenderTarget_D3D(this);
  217. }
  218. #endif // SE1_D3D
  219. }
  220. void CViewPort::SwapBuffers(void)
  221. {
  222. // skip if child window not present
  223. if( vp_hWnd==NULL) return;
  224. // ask the current driver to swap buffers
  225. _sfStats.StartTimer(CStatForm::STI_SWAPBUFFERS);
  226. _pfGfxProfile.StartTimer( CGfxProfile::PTI_SWAPBUFFERS);
  227. _pfGfxProfile.IncrementAveragingCounter(1);
  228. _pGfx->SwapBuffers(this);
  229. _pfGfxProfile.StopTimer( CGfxProfile::PTI_SWAPBUFFERS);
  230. _sfStats.StopTimer(CStatForm::STI_SWAPBUFFERS);
  231. }