|
@@ -323,25 +323,25 @@ bool VideoDriver_Win32::MakeWindow(bool
|
|
|
if (_wnd.main_wnd == nullptr) usererror("CreateWindow failed");
|
|
|
ShowWindow(_wnd.main_wnd, showstyle);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
BlitterFactory::GetCurrentBlitter()->PostResize();
|
|
|
|
|
|
GameSizeChanged(); // invalidate all windows, force redraw
|
|
|
return true; // the request succeeded
|
|
|
}
|
|
|
|
|
|
/** Do palette animation and blit to the window. */
|
|
|
static void PaintWindow()
|
|
|
void VideoDriver_Win32::Paint()
|
|
|
{
|
|
|
PerformanceMeasurer framerate(PFE_VIDEO);
|
|
|
|
|
|
if (IsEmptyRect(_dirty_rect)) return;
|
|
|
|
|
|
/* Convert update region from logical to device coordinates. */
|
|
|
POINT pt = {0, 0};
|
|
|
ClientToScreen(_wnd.main_wnd, &pt);
|
|
|
|
|
|
RECT r = { _dirty_rect.left, _dirty_rect.top, _dirty_rect.right, _dirty_rect.bottom };
|
|
|
OffsetRect(&r, pt.x, pt.y);
|
|
|
|
|
@@ -376,43 +376,48 @@ static void PaintWindow()
|
|
|
}
|
|
|
|
|
|
BitBlt(dc, 0, 0, _wnd.width, _wnd.height, dc2, 0, 0, SRCCOPY);
|
|
|
SelectPalette(dc, old_palette, TRUE);
|
|
|
SelectObject(dc2, old_bmp);
|
|
|
DeleteDC(dc2);
|
|
|
|
|
|
ReleaseDC(_wnd.main_wnd, dc);
|
|
|
|
|
|
MemSetT(&_dirty_rect, 0);
|
|
|
}
|
|
|
|
|
|
static void PaintWindowThread()
|
|
|
void VideoDriver_Win32::PaintThread()
|
|
|
{
|
|
|
/* First tell the main thread we're started */
|
|
|
std::unique_lock<std::recursive_mutex> lock(*_draw_mutex);
|
|
|
_draw_signal->notify_one();
|
|
|
|
|
|
/* Now wait for the first thing to draw! */
|
|
|
_draw_signal->wait(*_draw_mutex);
|
|
|
|
|
|
while (_draw_continue) {
|
|
|
PaintWindow();
|
|
|
this->Paint();
|
|
|
|
|
|
/* Flush GDI buffer to ensure drawing here doesn't conflict with any GDI usage in the main WndProc. */
|
|
|
GdiFlush();
|
|
|
|
|
|
_draw_signal->wait(*_draw_mutex);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/* static */ void VideoDriver_Win32::PaintThreadThunk(VideoDriver_Win32 *drv)
|
|
|
{
|
|
|
drv->PaintThread();
|
|
|
}
|
|
|
|
|
|
/** Forward key presses to the window system. */
|
|
|
static LRESULT HandleCharMsg(uint keycode, WChar charcode)
|
|
|
{
|
|
|
#if !defined(UNICODE)
|
|
|
static char prev_char = 0;
|
|
|
|
|
|
char input[2] = {(char)charcode, 0};
|
|
|
int input_len = 1;
|
|
|
|
|
|
if (prev_char != 0) {
|
|
|
/* We stored a lead byte previously, combine it with this byte. */
|
|
|
input[0] = prev_char;
|
|
@@ -1167,25 +1172,25 @@ void VideoDriver_Win32::MainLoop()
|
|
|
* directly in the newly created thread. */
|
|
|
try {
|
|
|
_draw_signal = new std::condition_variable_any();
|
|
|
_draw_mutex = new std::recursive_mutex();
|
|
|
} catch (...) {
|
|
|
_draw_threaded = false;
|
|
|
}
|
|
|
|
|
|
if (_draw_threaded) {
|
|
|
this->draw_lock = std::unique_lock<std::recursive_mutex>(*_draw_mutex);
|
|
|
|
|
|
_draw_continue = true;
|
|
|
_draw_threaded = StartNewThread(&draw_thread, "ottd:draw-win32", &PaintWindowThread);
|
|
|
_draw_threaded = StartNewThread(&draw_thread, "ottd:draw-win32", &VideoDriver_Win32::PaintThreadThunk, this);
|
|
|
|
|
|
/* Free the mutex if we won't be able to use it. */
|
|
|
if (!_draw_threaded) {
|
|
|
this->draw_lock.unlock();
|
|
|
this->draw_lock.release();
|
|
|
delete _draw_mutex;
|
|
|
delete _draw_signal;
|
|
|
_draw_mutex = nullptr;
|
|
|
_draw_signal = nullptr;
|
|
|
} else {
|
|
|
DEBUG(driver, 1, "Threaded drawing enabled");
|
|
|
/* Wait till the draw thread has started itself. */
|
|
@@ -1245,25 +1250,25 @@ void VideoDriver_Win32::MainLoop()
|
|
|
|
|
|
/* Flush GDI buffer to ensure we don't conflict with the drawing thread. */
|
|
|
GdiFlush();
|
|
|
|
|
|
this->InputLoop();
|
|
|
::InputLoop();
|
|
|
UpdateWindows();
|
|
|
CheckPaletteAnim();
|
|
|
|
|
|
if (_draw_mutex != nullptr && !HasModalProgress()) {
|
|
|
_draw_signal->notify_one();
|
|
|
} else {
|
|
|
PaintWindow();
|
|
|
this->Paint();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/* If we are not in fast-forward, create some time between calls to ease up CPU usage. */
|
|
|
if (!_fast_forward || _pause_mode) {
|
|
|
/* See how much time there is till we have to process the next event, and try to hit that as close as possible. */
|
|
|
auto next_tick = std::min(next_draw_tick, next_game_tick);
|
|
|
auto now = std::chrono::steady_clock::now();
|
|
|
|
|
|
if (next_tick > now) {
|
|
|
/* Flush GDI buffer to ensure we don't conflict with the drawing thread. */
|
|
|
GdiFlush();
|