in the normal d3d application, when we resize the window or drag the window, it will block the main thread.
if it is a online-game, it will block the logic.
so i want to find a method to resolve the problem.
in my option, multi thread is a proper resolution,
so i create the window( CreateWindowEx ) in the special thread, and call PeekMessage in that thread, like this:
UINT GameWindow::Exec()
{
HINSTANCE hInst = 0;
hInst = (HINSTANCE)::GetModuleHandle(NULL);
// register window
WNDCLASSEX wc = {0};
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = StaticClientWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInst;
wc.hIcon = LoadIcon(0, IDI_WINLOGO);
wc.hCursor = LoadCursor(0, IDC_ARROW);
//wc.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH);
wc.hbrBackground = NULL;
wc.lpszMenuName = 0;
wc.lpszClassName = L"xxxxxMainWindow";
if( !RegisterClassExW(&wc) )
{
LogError( _T("Can't Register Window Class:") _T("HikariMainWindow") );
LogError( _T("Last Error:"), System::Error::GetErrorDesc() );
return false;
}
DWORD WindowStyle;
WindowStyle = WS_OVERLAPPEDWINDOW;
// Create Window
m_WndID = CreateWindowExW(
WS_EX_APPWINDOW,
L"MainWindow",
Detail::UTF8ToWCHAR(m_strTitle).CStr(),
WindowStyle,
CW_USEDEFAULT, CW_USEDEFAULT, m_SizeX, m_SizeY,
NULL,
NULL,
hInst,
NULL );
// ......
m_CreateWindowEvent.Trigger();
MSG msg = {0};
do
{
while( PeekMessage( &msg, 0, 0, 0, PM_REMOVE ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
}while( !IsRequestExit() );
return 0;
}
so the WndProc will called in this thread, in this function, i send all the parameters to main thread.
and in main thread, i open the message queue, process all the messages.
LRESULT GameWindow::StaticClientWndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
X_ASSERT( g_WindowsMessageDisptacher );
SendWindowsEventImpl(
true,
g_WindowsMessageDisptacher,
WindowsMessageCommandDispatcher::ALIGN_SIZE,
HWND, hWnd, hwnd,
UINT, message, msg,
WPARAM, w, wParam,
LPARAM, h, lParam
);
return ::DefWindowProc( hwnd, msg, wParam, lParam );
}
in the main thread.
void GameWindow::ProcessGameWindowEvent( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
switch( msg )
{
case WM_DESTROY:
::PostQuitMessage(0);
break;
case WM_CLOSE:
m_bRequestExit = true;
g_GameEngine->RequestQuit();
break;
case WM_SIZE:
if( g_GameEngine && wParam == SIZE_RESTORED )
{
// g_GameEngine->OnGameWindowResize( LOWORD(lParam), HIWORD(lParam) );
}
break;
}
}
it works well if i just drag the window, the main thread and its main loop is not blocked.
the question is when i resize the window, there is a render error when i call
IDirect3DSwapChain9::Present
Direct3D9: (ERROR) :BitBlt or StretchBlt failed in Present
if i ignore this error, it will work well in next frame.
so i want to know how to avoid this error when i create window in individual thread.
is there any articles or topics?
my render work is also doing in the individual thread.