123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274 |
- /* Copyright (c) 2002-2012 Croteam Ltd.
- This program is free software; you can redistribute it and/or modify
- it under the terms of version 2 of the GNU General Public License as published by
- the Free Software Foundation
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
- #include "stdh.h"
- #include <Engine/Graphics/ViewPort.h>
- #include <Engine/Graphics/GfxProfile.h>
- #include <Engine/Graphics/GfxLibrary.h>
- #include <Engine/Base/Statistics_internal.h>
- extern INDEX ogl_bExclusive;
- // helper for D3D surface
- #ifdef SE1_D3D
- static void CreateSwapChain_D3D( CViewPort *pvp, PIX pixSizeI, PIX pixSizeJ)
- {
- HRESULT hr;
- D3DPRESENT_PARAMETERS d3dPresentParams;
- memset( &d3dPresentParams, 0, sizeof(d3dPresentParams));
- d3dPresentParams.Windowed = TRUE;
- d3dPresentParams.BackBufferWidth = pixSizeI;
- d3dPresentParams.BackBufferHeight = pixSizeJ;
- d3dPresentParams.BackBufferFormat = _pGfx->gl_d3dColorFormat;
- d3dPresentParams.BackBufferCount = 1;
- d3dPresentParams.MultiSampleType = D3DMULTISAMPLE_NONE; // !!!! TODO
- d3dPresentParams.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
- d3dPresentParams.SwapEffect = D3DSWAPEFFECT_DISCARD;
- d3dPresentParams.hDeviceWindow = pvp->vp_hWnd;
- ASSERT( pvp->vp_pSwapChain==NULL && pvp->vp_pSurfDepth==NULL);
- hr = _pGfx->gl_pd3dDevice->CreateAdditionalSwapChain( &d3dPresentParams, &pvp->vp_pSwapChain);
- D3D_CHECKERROR(hr);
- hr = _pGfx->gl_pd3dDevice->CreateDepthStencilSurface( pixSizeI, pixSizeJ, _pGfx->gl_d3dDepthFormat,
- D3DMULTISAMPLE_NONE, &pvp->vp_pSurfDepth);
- D3D_CHECKERROR(hr);
- ASSERT( pvp->vp_pSwapChain!=NULL);
- ASSERT( pvp->vp_pSurfDepth!=NULL);
- }
- static void SetAsRenderTarget_D3D( CViewPort *pvp)
- {
- HRESULT hr;
- LPDIRECT3DSURFACE8 pColorSurface;
- hr = pvp->vp_pSwapChain->GetBackBuffer( 0, D3DBACKBUFFER_TYPE_MONO, &pColorSurface);
- D3D_CHECKERROR(hr);
- hr = _pGfx->gl_pd3dDevice->SetRenderTarget( pColorSurface, pvp->vp_pSurfDepth);
- D3D_CHECKERROR(hr);
- D3DRELEASE( pColorSurface, TRUE);
- }
- #endif // SE1_D3D
- // helper for OGL
- CTempDC::CTempDC(HWND hWnd)
- {
- ASSERT(hWnd!=NULL);
- hwnd = hWnd;
- hdc = GetDC(hwnd);
- ASSERT(hdc!=NULL);
- }
- CTempDC::~CTempDC(void)
- {
- ReleaseDC(hwnd, hdc);
- }
- /*
- * ViewPort functions
- */
- CViewPort::CViewPort( PIX pixWidth, PIX pixHeight, HWND hWnd) :
- vp_Raster( pixWidth, pixHeight, 0)
- {
- vp_hWnd = NULL;
- vp_hWndParent = hWnd;
- #ifdef SE1_D3D
- vp_pSwapChain = NULL;
- vp_pSurfDepth = NULL;
- #endif // SE1_D3D
- vp_ctDisplayChanges = 0;
- OpenCanvas();
- vp_Raster.ra_pvpViewPort = this;
- }
- CViewPort::~CViewPort(void)
- {
- CloseCanvas(TRUE);
- // reset current viewport if needed
- if( _pGfx->gl_pvpActive==this) _pGfx->gl_pvpActive = NULL;
- }
- #define CViewPortCLASS "ViewPort Window"
- static BOOL _bClassRegistered = FALSE;
- LRESULT CALLBACK CViewPortCLASS_WindowProc(
- HWND hWnd, // handle to window
- UINT Msg, // message identifier
- WPARAM wParam, // first message parameter
- LPARAM lParam // second message parameter
- )
- {
- // forget erase bacground messages
- if (Msg==WM_ERASEBKGND) return TRUE;
- // if any mouse message
- if ((Msg>=WM_MOUSEFIRST&&Msg<=WM_MOUSELAST)) {
- // send it to parent
- HWND hWndParent = GetParent(hWnd);
- ASSERT(hWndParent!=NULL);
- return CallWindowProc( (WNDPROC)GetWindowLong(hWndParent, GWL_WNDPROC),
- hWndParent, Msg, wParam, lParam);
- }
- return DefWindowProc(hWnd, Msg, wParam, lParam);
- }
- // open overlaid window for rendering context
- void CViewPort::OpenCanvas(void)
- {
- // do nothing if not feasable
- if( vp_hWnd!=NULL || vp_hWndParent==NULL) return;
- // register class
- if( !_bClassRegistered) {
- WNDCLASSA wc;
- wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
- wc.lpfnWndProc = CViewPortCLASS_WindowProc;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = 0;
- wc.hInstance = NULL;
- wc.hIcon = NULL;
- wc.hCursor = LoadCursor( NULL, IDC_ARROW);
- wc.hbrBackground = NULL;
- wc.lpszMenuName = NULL;
- wc.lpszClassName = CViewPortCLASS;
- RegisterClassA(&wc);
- _bClassRegistered = TRUE;
- }
-
- // determine window and desktopsize
- RECT rectWindow;
- GetClientRect( vp_hWndParent, &rectWindow);
- const PIX pixWinSizeI = rectWindow.right - rectWindow.left;
- const PIX pixWinSizeJ = rectWindow.bottom - rectWindow.top;
- CDisplayMode dm;
- _pGfx->GetCurrentDisplayMode(dm);
- ASSERT( (dm.dm_pixSizeI==0 && dm.dm_pixSizeJ==0) || (dm.dm_pixSizeI!=0 && dm.dm_pixSizeJ!=0));
- const BOOL bFullScreen = (dm.dm_pixSizeI==pixWinSizeI && dm.dm_pixSizeJ==pixWinSizeJ);
- // set fullscreen attribs if window size is equal to screen size
- DWORD dwExStyle = NONE;
- DWORD dwStyle = WS_CHILD|WS_CLIPCHILDREN|WS_CLIPSIBLINGS;
- if( bFullScreen && ogl_bExclusive) {
- dwExStyle = WS_EX_TOPMOST;
- dwStyle = WS_POPUP;
- }
- // set child window
- vp_hWnd = ::CreateWindowExA(
- dwExStyle,
- CViewPortCLASS,
- "", // title
- dwStyle,
- 0,0,
- 0,0, // window size
- vp_hWndParent,
- NULL,
- (HINSTANCE)GetWindowLong(vp_hWndParent, GWL_HINSTANCE),
- NULL);
- ASSERT( vp_hWnd!=NULL);
- #ifdef SE1_D3D
- // prepare new swap chain for D3D
- if( _pGfx->gl_eCurrentAPI==GAT_D3D && !bFullScreen) CreateSwapChain_D3D( this, pixWinSizeI, pixWinSizeJ);
- #endif // SE1_D3D
- // resize raster
- Resize();
- ShowWindow( vp_hWnd, SW_SHOW);
- #ifdef SE1_D3D
- // set as rendering target
- if( _pGfx->gl_eCurrentAPI==GAT_D3D && vp_pSwapChain!=NULL) SetAsRenderTarget_D3D(this);
- #endif // SE1_D3D
- }
- // close overlaid window
- void CViewPort::CloseCanvas( BOOL bRelease/*=FALSE*/)
- {
- // release D3D swap chain if allocated
- #ifdef SE1_D3D
- if( _pGfx->gl_eCurrentAPI==GAT_D3D && bRelease) {
- if( vp_pSwapChain!=NULL) D3DRELEASE( vp_pSwapChain, TRUE);
- if( vp_pSurfDepth!=NULL) D3DRELEASE( vp_pSurfDepth, TRUE);
- }
- #endif // SE1_D3D
- // destroy window
- if( vp_hWnd!=NULL && IsWindow(vp_hWnd)) {
- BOOL bRes = DestroyWindow(vp_hWnd);
- ASSERT(bRes);
- }
- // mark
- vp_hWnd = NULL;
- #ifdef SE1_D3D
- vp_pSwapChain = NULL;
- vp_pSurfDepth = NULL;
- #endif // SE1_D3D
- }
- // Change size of this viewport, it's raster and all it's drawports
- void CViewPort::Resize(void)
- {
- PIX pixNewWidth, pixNewHeight;
- RECT rectWindow;
- // get the size of the window
- GetClientRect( vp_hWndParent, &rectWindow);
- pixNewWidth = rectWindow.right - rectWindow.left;
- pixNewHeight = rectWindow.bottom - rectWindow.top;
- // resize child window
- ASSERT( vp_hWnd!=NULL);
- SetWindowPos( vp_hWnd, NULL, 0,0, pixNewWidth, pixNewHeight, SWP_NOZORDER|SWP_NOMOVE);
- // resize the raster
- vp_Raster.Resize( pixNewWidth, pixNewHeight);
- // "resize" D3D surface (if any)
- #ifdef SE1_D3D
- if( _pGfx->gl_eCurrentAPI==GAT_D3D && vp_pSwapChain!=NULL) {
- // release old surface
- ASSERT( vp_pSurfDepth!=NULL);
- D3DRELEASE( vp_pSwapChain, TRUE);
- D3DRELEASE( vp_pSurfDepth, TRUE);
- // create a new one and set it as current
- CreateSwapChain_D3D( this, pixNewWidth, pixNewHeight);
- SetAsRenderTarget_D3D(this);
- }
- #endif // SE1_D3D
- }
- void CViewPort::SwapBuffers(void)
- {
- // skip if child window not present
- if( vp_hWnd==NULL) return;
- // ask the current driver to swap buffers
- _sfStats.StartTimer(CStatForm::STI_SWAPBUFFERS);
- _pfGfxProfile.StartTimer( CGfxProfile::PTI_SWAPBUFFERS);
- _pfGfxProfile.IncrementAveragingCounter(1);
- _pGfx->SwapBuffers(this);
- _pfGfxProfile.StopTimer( CGfxProfile::PTI_SWAPBUFFERS);
- _sfStats.StopTimer(CStatForm::STI_SWAPBUFFERS);
- }
|