|
@@ -41,10 +41,7 @@
|
|
|
#endif
|
|
|
|
|
|
static struct {
|
|
|
HWND main_wnd; ///< Handle to system window.
|
|
|
HBITMAP dib_sect; ///< System bitmap object referencing our rendering buffer.
|
|
|
void *buffer_bits; ///< Internal rendering buffer.
|
|
|
HPALETTE gdi_palette; ///< Palette object for 8bpp blitter.
|
|
|
int width; ///< Width in pixels of our display surface.
|
|
|
int height; ///< Height in pixels of our display surface.
|
|
|
int width_org; ///< Original monitor resolution width, before we changed it.
|
|
@@ -71,43 +68,6 @@ static Palette _local_palette;
|
|
|
/** Region of the screen that needs redrawing. */
|
|
|
static Rect _dirty_rect;
|
|
|
|
|
|
static void MakePalette()
|
|
|
{
|
|
|
_cur_palette.first_dirty = 0;
|
|
|
_cur_palette.count_dirty = 256;
|
|
|
_local_palette = _cur_palette;
|
|
|
|
|
|
LOGPALETTE *pal = (LOGPALETTE*)alloca(sizeof(LOGPALETTE) + (256 - 1) * sizeof(PALETTEENTRY));
|
|
|
|
|
|
pal->palVersion = 0x300;
|
|
|
pal->palNumEntries = 256;
|
|
|
|
|
|
for (uint i = 0; i != 256; i++) {
|
|
|
pal->palPalEntry[i].peRed = _local_palette.palette[i].r;
|
|
|
pal->palPalEntry[i].peGreen = _local_palette.palette[i].g;
|
|
|
pal->palPalEntry[i].peBlue = _local_palette.palette[i].b;
|
|
|
pal->palPalEntry[i].peFlags = 0;
|
|
|
|
|
|
}
|
|
|
_wnd.gdi_palette = CreatePalette(pal);
|
|
|
if (_wnd.gdi_palette == nullptr) usererror("CreatePalette failed!\n");
|
|
|
}
|
|
|
|
|
|
static void UpdatePalette(HDC dc, uint start, uint count)
|
|
|
{
|
|
|
RGBQUAD rgb[256];
|
|
|
uint i;
|
|
|
|
|
|
for (i = 0; i != count; i++) {
|
|
|
rgb[i].rgbRed = _local_palette.palette[start + i].r;
|
|
|
rgb[i].rgbGreen = _local_palette.palette[start + i].g;
|
|
|
rgb[i].rgbBlue = _local_palette.palette[start + i].b;
|
|
|
rgb[i].rgbReserved = 0;
|
|
|
}
|
|
|
|
|
|
SetDIBColorTable(dc, start, count, rgb);
|
|
|
}
|
|
|
|
|
|
bool VideoDriver_Win32Base::ClaimMousePointer()
|
|
|
{
|
|
|
MyShowCursor(false, true);
|
|
@@ -182,33 +142,6 @@ static uint MapWindowsKey(uint sym)
|
|
|
return key;
|
|
|
}
|
|
|
|
|
|
#ifdef _DEBUG
|
|
|
/* Keep this function here..
|
|
|
* It allows you to redraw the screen from within the MSVC debugger */
|
|
|
int RedrawScreenDebug()
|
|
|
{
|
|
|
HDC dc, dc2;
|
|
|
static int _fooctr;
|
|
|
HBITMAP old_bmp;
|
|
|
HPALETTE old_palette;
|
|
|
|
|
|
UpdateWindows();
|
|
|
|
|
|
dc = GetDC(_wnd.main_wnd);
|
|
|
dc2 = CreateCompatibleDC(dc);
|
|
|
|
|
|
old_bmp = (HBITMAP)SelectObject(dc2, _wnd.dib_sect);
|
|
|
old_palette = SelectPalette(dc, _wnd.gdi_palette, FALSE);
|
|
|
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);
|
|
|
|
|
|
return _fooctr++;
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
/**
|
|
|
* Instantiate a new window.
|
|
|
* @param full_screen Whether to make a full screen window or not.
|
|
@@ -221,9 +154,9 @@ bool VideoDriver_Win32Base::MakeWindow(b
|
|
|
_fullscreen = full_screen;
|
|
|
|
|
|
/* recreate window? */
|
|
|
if ((full_screen || _wnd.fullscreen) && _wnd.main_wnd) {
|
|
|
DestroyWindow(_wnd.main_wnd);
|
|
|
_wnd.main_wnd = 0;
|
|
|
if ((full_screen || _wnd.fullscreen) && this->main_wnd) {
|
|
|
DestroyWindow(this->main_wnd);
|
|
|
this->main_wnd = 0;
|
|
|
}
|
|
|
|
|
|
if (full_screen) {
|
|
@@ -289,8 +222,8 @@ bool VideoDriver_Win32Base::MakeWindow(b
|
|
|
w = r.right - r.left;
|
|
|
h = r.bottom - r.top;
|
|
|
|
|
|
if (_wnd.main_wnd != nullptr) {
|
|
|
if (!_window_maximize) SetWindowPos(_wnd.main_wnd, 0, 0, 0, w, h, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER | SWP_NOMOVE);
|
|
|
if (this->main_wnd != nullptr) {
|
|
|
if (!_window_maximize) SetWindowPos(this->main_wnd, 0, 0, 0, w, h, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER | SWP_NOMOVE);
|
|
|
} else {
|
|
|
int x = (GetSystemMetrics(SM_CXSCREEN) - w) / 2;
|
|
|
int y = (GetSystemMetrics(SM_CYSCREEN) - h) / 2;
|
|
@@ -298,16 +231,16 @@ bool VideoDriver_Win32Base::MakeWindow(b
|
|
|
char window_title[64];
|
|
|
seprintf(window_title, lastof(window_title), "OpenTTD %s", _openttd_revision);
|
|
|
|
|
|
_wnd.main_wnd = CreateWindow(_T("OTTD"), MB_TO_WIDE(window_title), style, x, y, w, h, 0, 0, GetModuleHandle(nullptr), this);
|
|
|
if (_wnd.main_wnd == nullptr) usererror("CreateWindow failed");
|
|
|
ShowWindow(_wnd.main_wnd, showstyle);
|
|
|
this->main_wnd = CreateWindow(_T("OTTD"), MB_TO_WIDE(window_title), style, x, y, w, h, 0, 0, GetModuleHandle(nullptr), this);
|
|
|
if (this->main_wnd == nullptr) usererror("CreateWindow failed");
|
|
|
ShowWindow(this->main_wnd, showstyle);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
BlitterFactory::GetCurrentBlitter()->PostResize();
|
|
|
|
|
|
GameSizeChanged(); // invalidate all windows, force redraw
|
|
|
return true; // the request succeeded
|
|
|
GameSizeChanged();
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
/* static */ void VideoDriver_Win32Base::PaintThreadThunk(VideoDriver_Win32Base *drv)
|
|
@@ -1077,7 +1010,7 @@ bool VideoDriver_Win32Base::ChangeResolu
|
|
|
std::unique_lock<std::recursive_mutex> lock;
|
|
|
if (_draw_mutex != nullptr) lock = std::unique_lock<std::recursive_mutex>(*_draw_mutex);
|
|
|
|
|
|
if (_window_maximize) ShowWindow(_wnd.main_wnd, SW_SHOWNORMAL);
|
|
|
if (_window_maximize) ShowWindow(this->main_wnd, SW_SHOWNORMAL);
|
|
|
|
|
|
_wnd.width = _wnd.width_org = w;
|
|
|
_wnd.height = _wnd.height_org = h;
|
|
@@ -1108,9 +1041,9 @@ void VideoDriver_Win32Base::EditBoxLostF
|
|
|
std::unique_lock<std::recursive_mutex> lock;
|
|
|
if (_draw_mutex != nullptr) lock = std::unique_lock<std::recursive_mutex>(*_draw_mutex);
|
|
|
|
|
|
CancelIMEComposition(_wnd.main_wnd);
|
|
|
SetCompositionPos(_wnd.main_wnd);
|
|
|
SetCandidatePos(_wnd.main_wnd);
|
|
|
CancelIMEComposition(this->main_wnd);
|
|
|
SetCompositionPos(this->main_wnd);
|
|
|
SetCandidatePos(this->main_wnd);
|
|
|
}
|
|
|
|
|
|
Dimension VideoDriver_Win32Base::GetScreenSize() const
|
|
@@ -1139,14 +1072,14 @@ float VideoDriver_Win32Base::GetDPIScale
|
|
|
|
|
|
UINT cur_dpi = 0;
|
|
|
|
|
|
if (cur_dpi == 0 && _GetDpiForWindow != nullptr && _wnd.main_wnd != nullptr) {
|
|
|
if (cur_dpi == 0 && _GetDpiForWindow != nullptr && this->main_wnd != nullptr) {
|
|
|
/* Per window DPI is supported since Windows 10 Ver 1607. */
|
|
|
cur_dpi = _GetDpiForWindow(_wnd.main_wnd);
|
|
|
cur_dpi = _GetDpiForWindow(this->main_wnd);
|
|
|
}
|
|
|
if (cur_dpi == 0 && _GetDpiForMonitor != nullptr && _wnd.main_wnd != nullptr) {
|
|
|
if (cur_dpi == 0 && _GetDpiForMonitor != nullptr && this->main_wnd != nullptr) {
|
|
|
/* Per monitor is supported since Windows 8.1. */
|
|
|
UINT dpiX, dpiY;
|
|
|
if (SUCCEEDED(_GetDpiForMonitor(MonitorFromWindow(_wnd.main_wnd, MONITOR_DEFAULTTOPRIMARY), 0 /* MDT_EFFECTIVE_DPI */, &dpiX, &dpiY))) {
|
|
|
if (SUCCEEDED(_GetDpiForMonitor(MonitorFromWindow(this->main_wnd, MONITOR_DEFAULTTOPRIMARY), 0 /* MDT_EFFECTIVE_DPI */, &dpiX, &dpiY))) {
|
|
|
cur_dpi = dpiX; // X and Y are always identical.
|
|
|
}
|
|
|
}
|
|
@@ -1182,7 +1115,7 @@ const char *VideoDriver_Win32GDI::Start(
|
|
|
|
|
|
RegisterWndClass();
|
|
|
|
|
|
MakePalette();
|
|
|
this->MakePalette();
|
|
|
|
|
|
FindResolutions();
|
|
|
|
|
@@ -1204,9 +1137,9 @@ const char *VideoDriver_Win32GDI::Start(
|
|
|
|
|
|
void VideoDriver_Win32GDI::Stop()
|
|
|
{
|
|
|
DeleteObject(_wnd.gdi_palette);
|
|
|
DeleteObject(_wnd.dib_sect);
|
|
|
DestroyWindow(_wnd.main_wnd);
|
|
|
DeleteObject(this->gdi_palette);
|
|
|
DeleteObject(this->dib_sect);
|
|
|
DestroyWindow(this->main_wnd);
|
|
|
|
|
|
if (_wnd.fullscreen) ChangeDisplaySettings(nullptr, 0);
|
|
|
MyShowCursor(true);
|
|
@@ -1232,11 +1165,11 @@ bool VideoDriver_Win32GDI::AllocateBacki
|
|
|
bi->bmiHeader.biBitCount = bpp;
|
|
|
bi->bmiHeader.biCompression = BI_RGB;
|
|
|
|
|
|
if (_wnd.dib_sect) DeleteObject(_wnd.dib_sect);
|
|
|
if (this->dib_sect) DeleteObject(this->dib_sect);
|
|
|
|
|
|
HDC dc = GetDC(0);
|
|
|
_wnd.dib_sect = CreateDIBSection(dc, bi, DIB_RGB_COLORS, (VOID **)&_wnd.buffer_bits, nullptr, 0);
|
|
|
if (_wnd.dib_sect == nullptr) usererror("CreateDIBSection failed");
|
|
|
this->dib_sect = CreateDIBSection(dc, bi, DIB_RGB_COLORS, (VOID **)&_wnd.buffer_bits, nullptr, 0);
|
|
|
if (this->dib_sect == nullptr) usererror("CreateDIBSection failed");
|
|
|
ReleaseDC(0, dc);
|
|
|
|
|
|
_screen.width = w;
|
|
@@ -1253,10 +1186,46 @@ bool VideoDriver_Win32GDI::AfterBlitterC
|
|
|
return this->AllocateBackingStore(_screen.width, _screen.height, true) && this->MakeWindow(_fullscreen);
|
|
|
}
|
|
|
|
|
|
void VideoDriver_Win32GDI::MakePalette()
|
|
|
{
|
|
|
_cur_palette.first_dirty = 0;
|
|
|
_cur_palette.count_dirty = 256;
|
|
|
_local_palette = _cur_palette;
|
|
|
|
|
|
LOGPALETTE *pal = (LOGPALETTE*)alloca(sizeof(LOGPALETTE) + (256 - 1) * sizeof(PALETTEENTRY));
|
|
|
|
|
|
pal->palVersion = 0x300;
|
|
|
pal->palNumEntries = 256;
|
|
|
|
|
|
for (uint i = 0; i != 256; i++) {
|
|
|
pal->palPalEntry[i].peRed = _local_palette.palette[i].r;
|
|
|
pal->palPalEntry[i].peGreen = _local_palette.palette[i].g;
|
|
|
pal->palPalEntry[i].peBlue = _local_palette.palette[i].b;
|
|
|
pal->palPalEntry[i].peFlags = 0;
|
|
|
|
|
|
}
|
|
|
this->gdi_palette = CreatePalette(pal);
|
|
|
if (this->gdi_palette == nullptr) usererror("CreatePalette failed!\n");
|
|
|
}
|
|
|
|
|
|
void VideoDriver_Win32GDI::UpdatePalette(HDC dc, uint start, uint count)
|
|
|
{
|
|
|
RGBQUAD rgb[256];
|
|
|
|
|
|
for (uint i = 0; i != count; i++) {
|
|
|
rgb[i].rgbRed = _local_palette.palette[start + i].r;
|
|
|
rgb[i].rgbGreen = _local_palette.palette[start + i].g;
|
|
|
rgb[i].rgbBlue = _local_palette.palette[start + i].b;
|
|
|
rgb[i].rgbReserved = 0;
|
|
|
}
|
|
|
|
|
|
SetDIBColorTable(dc, start, count, rgb);
|
|
|
}
|
|
|
|
|
|
void VideoDriver_Win32GDI::PaletteChanged(HWND hWnd)
|
|
|
{
|
|
|
HDC hDC = GetWindowDC(hWnd);
|
|
|
HPALETTE hOldPalette = SelectPalette(hDC, _wnd.gdi_palette, FALSE);
|
|
|
HPALETTE hOldPalette = SelectPalette(hDC, this->gdi_palette, FALSE);
|
|
|
UINT nChanged = RealizePalette(hDC);
|
|
|
|
|
|
SelectPalette(hDC, hOldPalette, TRUE);
|
|
@@ -1270,18 +1239,18 @@ void VideoDriver_Win32GDI::Paint()
|
|
|
|
|
|
if (IsEmptyRect(_dirty_rect)) return;
|
|
|
|
|
|
HDC dc = GetDC(_wnd.main_wnd);
|
|
|
HDC dc = GetDC(this->main_wnd);
|
|
|
HDC dc2 = CreateCompatibleDC(dc);
|
|
|
|
|
|
HBITMAP old_bmp = (HBITMAP)SelectObject(dc2, _wnd.dib_sect);
|
|
|
HPALETTE old_palette = SelectPalette(dc, _wnd.gdi_palette, FALSE);
|
|
|
HBITMAP old_bmp = (HBITMAP)SelectObject(dc2, this->dib_sect);
|
|
|
HPALETTE old_palette = SelectPalette(dc, this->gdi_palette, FALSE);
|
|
|
|
|
|
if (_cur_palette.count_dirty != 0) {
|
|
|
Blitter *blitter = BlitterFactory::GetCurrentBlitter();
|
|
|
|
|
|
switch (blitter->UsePaletteAnimation()) {
|
|
|
case Blitter::PALETTE_ANIMATION_VIDEO_BACKEND:
|
|
|
UpdatePalette(dc2, _local_palette.first_dirty, _local_palette.count_dirty);
|
|
|
this->UpdatePalette(dc2, _local_palette.first_dirty, _local_palette.count_dirty);
|
|
|
break;
|
|
|
|
|
|
case Blitter::PALETTE_ANIMATION_BLITTER:
|
|
@@ -1302,7 +1271,7 @@ void VideoDriver_Win32GDI::Paint()
|
|
|
SelectObject(dc2, old_bmp);
|
|
|
DeleteDC(dc2);
|
|
|
|
|
|
ReleaseDC(_wnd.main_wnd, dc);
|
|
|
ReleaseDC(this->main_wnd, dc);
|
|
|
|
|
|
_dirty_rect = {};
|
|
|
}
|
|
@@ -1325,3 +1294,23 @@ void VideoDriver_Win32GDI::PaintThread()
|
|
|
_draw_signal->wait(*_draw_mutex);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
#ifdef _DEBUG
|
|
|
/* Keep this function here..
|
|
|
* It allows you to redraw the screen from within the MSVC debugger */
|
|
|
/* static */ int VideoDriver_Win32GDI::RedrawScreenDebug()
|
|
|
{
|
|
|
static int _fooctr;
|
|
|
|
|
|
_screen.dst_ptr = _wnd.buffer_bits;
|
|
|
UpdateWindows();
|
|
|
|
|
|
VideoDriver_Win32GDI *drv = static_cast<VideoDriver_Win32GDI *>(VideoDriver::GetInstance());
|
|
|
|
|
|
drv->Paint();
|
|
|
GdiFlush();
|
|
|
|
|
|
return _fooctr++;
|
|
|
}
|
|
|
#endif
|