00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "KeosD3D9Window.h"
00023 #include "KeosD3D9Exception.h"
00024 #include "KeosLogger.h"
00025 #include "KeosD3D9RenderSystem.h"
00026 #include "KeosConsole.h"
00027
00028 namespace Keos
00029 {
00030
00031
00032
00033
00034
00035
00036 CD3D9Window::CD3D9Window(CD3D9* pD3D9)
00037 {
00038 m_pD3D9 = pD3D9;
00039 m_bIsFullScreen = false;
00040 m_HWnd = NULL;
00041 m_bActive = false;
00042 m_bSizing = false;
00043 m_bIsFullScreen = false;
00044 m_bReady = false;
00045 m_bClosed = false;
00046 }
00047
00048
00049 CD3D9Window::~CD3D9Window()
00050 {
00051 Destroy();
00052 }
00053
00054
00055 void CD3D9Window::Create(const String& strName, uint nWidth, uint nHeight, uint nColourDepth, bool bFullScreen)
00056 {
00057
00058 HINSTANCE hInst = GetModuleHandle( KEOS_D3D9_LIB );
00059
00060 m_FSAAType = D3DMULTISAMPLE_NONE;
00061 m_FSAAQuality = 0;
00062 m_bVSync = false;
00063 unsigned int displayFrequency = 0;
00064 String title = strName;
00065 unsigned int colourDepth = nColourDepth;
00066 int left = -1;
00067 int top = -1;
00068 bool depthBuffer = true;
00069 String border = "";
00070 bool outerSize = false;
00071
00072
00073 if ( m_HWnd )
00074 Destroy();
00075
00076 DWORD dwStyle = WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
00077 RECT rc;
00078
00079 m_nWidth = nWidth;
00080 m_nHeight = nHeight;
00081 m_nTop = top;
00082 m_nLeft = left;
00083
00084 if (!bFullScreen)
00085 {
00086 if (border == "none")
00087 dwStyle |= WS_POPUP;
00088 else if (border == "fixed")
00089 dwStyle |= WS_OVERLAPPED | WS_BORDER | WS_CAPTION |
00090 WS_SYSMENU | WS_MINIMIZEBOX;
00091 else
00092 dwStyle |= WS_OVERLAPPEDWINDOW;
00093
00094 if (!outerSize)
00095 {
00096
00097
00098 SetRect(&rc, 0, 0, m_nWidth, m_nHeight);
00099 AdjustWindowRect(&rc, dwStyle, false);
00100 m_nWidth = rc.right - rc.left;
00101 m_nHeight = rc.bottom - rc.top;
00102
00103
00104 int screenw = GetSystemMetrics(SM_CXSCREEN);
00105 int screenh = GetSystemMetrics(SM_CYSCREEN);
00106 if ((int)m_nWidth > screenw)
00107 m_nWidth = screenw;
00108 if ((int)m_nHeight > screenh)
00109 m_nHeight = screenh;
00110 if (m_nLeft < 0)
00111 m_nLeft = (screenw - m_nWidth) / 2;
00112 if (m_nTop < 0)
00113 m_nTop = (screenh - m_nHeight) / 2;
00114 }
00115 }
00116 else
00117 {
00118 dwStyle |= WS_POPUP;
00119 m_nTop = m_nLeft = 0;
00120 }
00121
00122
00123
00124 WNDCLASS wc =
00125 {
00126 0, WndProc, 0, 0, hInst,
00127 LoadIcon(0, IDI_APPLICATION), LoadCursor(NULL, IDC_ARROW),
00128 (HBRUSH)GetStockObject(BLACK_BRUSH), 0, "KeosD3D9Wnd"
00129 };
00130 RegisterClass(&wc);
00131
00132
00133
00134 m_HWnd = CreateWindow("KeosD3D9Wnd", title.c_str(), dwStyle,
00135 m_nLeft, m_nTop, m_nWidth, m_nHeight, (HWND) NULL, 0, hInst, this);
00136
00137
00138 GetWindowRect(m_HWnd, &rc);
00139 m_nTop = rc.top;
00140 m_nLeft = rc.left;
00141
00142 GetClientRect(m_HWnd, &rc);
00143 m_nWidth = rc.right;
00144 m_nHeight = rc.bottom;
00145
00146 m_strName = strName;
00147
00148 m_bIsFullScreen = bFullScreen;
00149 m_nColourDepth = colourDepth;
00150
00151 ILogger::Log("Created CD3D9Window '%s' : %dx%d, %dbpp",
00152 m_strName.c_str(), m_nWidth, m_nHeight, m_nColourDepth);
00153
00154 CreateD3DResources();
00155
00156 m_bActive = true;
00157 }
00158
00159 void CD3D9Window::CreateD3DResources(void)
00160 {
00161
00162 HRESULT hr;
00163 LPDIRECT3D9 pD3D = m_pD3D9->pD3D;
00164
00165 D3DDEVTYPE devType = D3DDEVTYPE_HAL;
00166
00167 ZeroMemory( &m_d3dpp, sizeof(D3DPRESENT_PARAMETERS) );
00168 m_d3dpp.Windowed = !m_bIsFullScreen;
00169 m_d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
00170 m_d3dpp.BackBufferCount = 1;
00171 m_d3dpp.EnableAutoDepthStencil = true;
00172 m_d3dpp.hDeviceWindow = m_HWnd;
00173 m_d3dpp.BackBufferWidth = m_nWidth;
00174 m_d3dpp.BackBufferHeight = m_nHeight;
00175
00176 if (m_bVSync)
00177 m_d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
00178 else
00179 m_d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
00180
00181 m_d3dpp.BackBufferFormat = D3DFMT_R5G6B5;
00182 if ( m_nColourDepth > 16 )
00183 m_d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
00184
00185 if (m_nColourDepth > 16 )
00186 {
00187
00188 if ( FAILED( pD3D->CheckDeviceFormat(D3DADAPTER_DEFAULT,
00189 devType, m_d3dpp.BackBufferFormat, D3DUSAGE_DEPTHSTENCIL,
00190 D3DRTYPE_SURFACE, D3DFMT_D24S8 )))
00191 {
00192
00193 if ( FAILED( pD3D->CheckDeviceFormat(D3DADAPTER_DEFAULT,
00194 devType, m_d3dpp.BackBufferFormat, D3DUSAGE_DEPTHSTENCIL,
00195 D3DRTYPE_SURFACE, D3DFMT_D32 )))
00196 {
00197
00198 m_d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
00199 }
00200 else
00201 m_d3dpp.AutoDepthStencilFormat = D3DFMT_D32;
00202 }
00203 else
00204 {
00205
00206 if ( SUCCEEDED( pD3D->CheckDepthStencilMatch( D3DADAPTER_DEFAULT, devType,
00207 m_d3dpp.BackBufferFormat, m_d3dpp.BackBufferFormat, D3DFMT_D24S8 ) ) )
00208 {
00209 m_d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
00210 }
00211 else
00212 m_d3dpp.AutoDepthStencilFormat = D3DFMT_D24X8;
00213 }
00214 }
00215 else
00216
00217 m_d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
00218
00219 m_d3dpp.MultiSampleType = m_FSAAType;
00220 m_d3dpp.MultiSampleQuality = (m_FSAAQuality == 0) ? 0 : m_FSAAQuality;
00221
00222
00223 if (!m_pD3D9->pD3DDevice)
00224 {
00225
00226
00227
00228 DWORD extraFlags = 0;
00229
00230 hr = pD3D->CreateDevice( D3DADAPTER_DEFAULT, devType, m_HWnd,
00231 D3DCREATE_HARDWARE_VERTEXPROCESSING | extraFlags, &m_d3dpp, &(m_pD3D9->pD3DDevice) );
00232 if ( FAILED( hr ) )
00233 {
00234 hr = pD3D->CreateDevice( D3DADAPTER_DEFAULT, devType, m_HWnd,
00235 D3DCREATE_MIXED_VERTEXPROCESSING | extraFlags, &m_d3dpp, &(m_pD3D9->pD3DDevice) );
00236 if ( FAILED( hr ) )
00237 {
00238 hr = pD3D->CreateDevice( D3DADAPTER_DEFAULT, devType, m_HWnd,
00239 D3DCREATE_SOFTWARE_VERTEXPROCESSING | extraFlags, &m_d3dpp, &(m_pD3D9->pD3DDevice) );
00240 }
00241 }
00242 if ( FAILED( hr ) )
00243 {
00244 Destroy();
00245 D3D9_EXCEPT("Failed to create Direct3D9 Device", "CD3D9Window::CreateD3DResources");
00246 }
00247 }
00248
00249 m_pD3D9->pD3DDevice->GetRenderTarget( 0, &m_pRenderSurface );
00250 m_pD3D9->pD3DDevice->GetDepthStencilSurface( &m_pRenderZBuffer );
00251
00252 if (m_pRenderSurface)m_pRenderSurface->Release();
00253 if (m_pRenderZBuffer) m_pRenderZBuffer->Release();
00254 }
00255
00256
00257 void CD3D9Window::Destroy(void)
00258 {
00259 m_pRenderSurface = 0;
00260 m_pRenderZBuffer = 0;
00261
00262 m_pD3D9->ReleaseDevice();
00263
00264 DestroyWindow( m_HWnd );
00265 m_HWnd = 0;
00266 m_bActive = false;
00267 }
00268
00269
00270 bool CD3D9Window::IsClosed() const
00271 {
00272 return m_bClosed;
00273 }
00274
00275
00276 void CD3D9Window::Reposition(int left, int top)
00277 {
00279 }
00280
00281
00282 void CD3D9Window::Resize(uint nWidth, uint nHeight)
00283 {
00284 m_nWidth = nWidth;
00285 m_nHeight = nHeight;
00286
00288 }
00289
00290
00291 void CD3D9Window::WindowMovedOrResized()
00292 {
00293 RECT temprect;
00294 ::GetClientRect(GetWindowHandle(), &temprect);
00295 Resize(temprect.right - temprect.left, temprect.bottom - temprect.top);
00296 }
00297
00298
00299 void CD3D9Window::SwapBuffers(bool bWaitForVSync)
00300 {
00301 if ( m_pD3D9->pD3DDevice )
00302 {
00303 HRESULT hr;
00304 hr = m_pD3D9->pD3DDevice->Present( NULL, NULL, NULL, NULL );
00305 if ( FAILED(hr) )
00306 {
00307 if (hr == D3DERR_DEVICELOST)
00308 {
00309 static_cast<CD3D9RenderSystem*>(
00310 CRoot::Instance().GetRenderSystem())->_NotifyDeviceLost();
00311 Sleep(500);
00312 }
00313 else D3D9_EXCEPT("Error Presenting surfaces", "CD3D9Window::SwapBuffers" );
00314 }
00315 }
00316 }
00317
00318
00319 void CD3D9Window::Update(void)
00320 {
00321 CD3D9RenderSystem* pRS = static_cast<CD3D9RenderSystem*>(
00322 CRoot::Instance().GetRenderSystem());
00323 if (pRS->IsDeviceLost())
00324 {
00325
00326 HRESULT hr = m_pD3D9->pD3DDevice->TestCooperativeLevel();
00327 if (hr == D3DERR_DEVICELOST)
00328 {
00329
00330
00331
00332
00333 m_pRenderSurface = 0;
00334 m_pRenderZBuffer = 0;
00335 Sleep(500);
00336 return;
00337 }
00338 else if (hr == D3DERR_DEVICENOTRESET)
00339 {
00340
00341 pRS->RestoreLostDevice();
00342
00343
00344 if (pRS->IsDeviceLost())
00345 {
00346
00347 Sleep(500);
00348 return;
00349 }
00350
00351
00352 m_pD3D9->pD3DDevice->GetRenderTarget( 0, &m_pRenderSurface );
00353 m_pD3D9->pD3DDevice->GetDepthStencilSurface( &m_pRenderZBuffer );
00354
00355 if (m_pRenderSurface) m_pRenderSurface->Release();
00356 if (m_pRenderZBuffer) m_pRenderZBuffer->Release();
00357 }
00358 }
00359 IRenderWindow::Update();
00360 }
00361
00362
00363 LRESULT CD3D9Window::WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
00364 {
00365 if (uMsg == WM_CREATE)
00366 {
00367
00368 SetWindowLong(hWnd, GWL_USERDATA,
00369 (LONG)(((LPCREATESTRUCT)lParam)->lpCreateParams));
00370 return 0;
00371 }
00372
00373 CD3D9Window* win =
00374 (CD3D9Window*)GetWindowLong(hWnd, GWL_USERDATA);
00375
00376 if (!win)
00377 return DefWindowProc(hWnd, uMsg, wParam, lParam);
00378
00379 switch ( uMsg )
00380 {
00381 case WM_ACTIVATE:
00382 win->m_bActive = (LOWORD(wParam) != WA_INACTIVE);
00383 break;
00384
00385 case WM_ENTERSIZEMOVE:
00386 win->m_bSizing = true;
00387 break;
00388
00389 case WM_EXITSIZEMOVE:
00390 win->WindowMovedOrResized();
00391 win->m_bSizing = false;
00392 break;
00393
00394 case WM_MOVE:
00395 case WM_SIZE:
00396 if (!win->m_bSizing)
00397 win->WindowMovedOrResized();
00398 break;
00399
00400 case WM_GETMINMAXINFO:
00401
00402 ((MINMAXINFO*)lParam)->ptMinTrackSize.x = 100;
00403 ((MINMAXINFO*)lParam)->ptMinTrackSize.y = 100;
00404 break;
00405
00406 case WM_CLOSE:
00407 win->Destroy();
00408 win->m_bClosed = true;
00409 return 0;
00410
00411
00412
00413 case WM_KEYDOWN:
00414 switch (wParam)
00415 {
00416 case VK_ESCAPE :
00417 win->m_bClosed = true;
00418 break;
00419 case VK_F1 :
00420 CConsole::Instance().Enable(true);
00421 break;
00422 case VK_F2 :
00423 CConsole::Instance().Enable(false);
00424 break;
00425 }
00426 break;
00427
00428 case WM_CHAR :
00429 CConsole::Instance().SendChar(static_cast<char>(LOWORD(wParam)));
00430 return 0;
00431
00432 }
00433
00434 return DefWindowProc( hWnd, uMsg, wParam, lParam );
00435 }
00436
00437 }