Codechange: [Win32] Move GDI-specific variables and related functions into the GDI video driver class.

This commit is contained in:
Michael Lutz 2021-01-16 16:43:02 +01:00
parent 8b90d4abe0
commit 78b8fc3e4f
2 changed files with 103 additions and 98 deletions

View File

@ -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(bool full_screen)
_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(bool full_screen)
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(bool full_screen)
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::ChangeResolution(int w, int h)
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::EditBoxLostFocus()
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(const StringList &param)
RegisterWndClass();
MakePalette();
this->MakePalette();
FindResolutions();
@ -1204,9 +1137,9 @@ const char *VideoDriver_Win32GDI::Start(const StringList &param)
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::AllocateBackingStore(int w, int h, bool force)
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::AfterBlitterChange()
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

View File

@ -15,6 +15,8 @@
/** Base class for Windows video drivers. */
class VideoDriver_Win32Base : public VideoDriver {
public:
VideoDriver_Win32Base() : main_wnd(nullptr) {}
void MakeDirty(int left, int top, int width, int height) override;
void MainLoop() override;
@ -32,6 +34,8 @@ public:
void EditBoxLostFocus() override;
protected:
HWND main_wnd; ///< Handle to system window.
Dimension GetScreenSize() const override;
float GetDPIScale() override;
void InputLoop() override;
@ -58,6 +62,8 @@ private:
/** The GDI video driver for windows. */
class VideoDriver_Win32GDI : public VideoDriver_Win32Base {
public:
VideoDriver_Win32GDI() : dib_sect(nullptr), gdi_palette(nullptr) {}
const char *Start(const StringList &param) override;
void Stop() override;
@ -67,11 +73,21 @@ public:
const char *GetName() const override { return "win32"; }
protected:
HBITMAP dib_sect; ///< System bitmap object referencing our rendering buffer.
HPALETTE gdi_palette; ///< Palette object for 8bpp blitter.
void Paint() override;
void PaintThread() override;
bool AllocateBackingStore(int w, int h, bool force = false) override;
void PaletteChanged(HWND hWnd) override;
void MakePalette();
void UpdatePalette(HDC dc, uint start, uint count);
#ifdef _DEBUG
public:
static int RedrawScreenDebug();
#endif
};
/** The factory for Windows' video driver. */