1
0
Fork 0

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

pull/8729/head
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 #endif
static struct { 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. void *buffer_bits; ///< Internal rendering buffer.
HPALETTE gdi_palette; ///< Palette object for 8bpp blitter.
int width; ///< Width in pixels of our display surface. int width; ///< Width in pixels of our display surface.
int height; ///< Height 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. 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. */ /** Region of the screen that needs redrawing. */
static Rect _dirty_rect; 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() bool VideoDriver_Win32Base::ClaimMousePointer()
{ {
MyShowCursor(false, true); MyShowCursor(false, true);
@ -182,33 +142,6 @@ static uint MapWindowsKey(uint sym)
return key; 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. * Instantiate a new window.
* @param full_screen Whether to make a full screen window or not. * @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; _fullscreen = full_screen;
/* recreate window? */ /* recreate window? */
if ((full_screen || _wnd.fullscreen) && _wnd.main_wnd) { if ((full_screen || _wnd.fullscreen) && this->main_wnd) {
DestroyWindow(_wnd.main_wnd); DestroyWindow(this->main_wnd);
_wnd.main_wnd = 0; this->main_wnd = 0;
} }
if (full_screen) { if (full_screen) {
@ -289,8 +222,8 @@ bool VideoDriver_Win32Base::MakeWindow(bool full_screen)
w = r.right - r.left; w = r.right - r.left;
h = r.bottom - r.top; h = r.bottom - r.top;
if (_wnd.main_wnd != nullptr) { if (this->main_wnd != nullptr) {
if (!_window_maximize) SetWindowPos(_wnd.main_wnd, 0, 0, 0, w, h, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER | SWP_NOMOVE); if (!_window_maximize) SetWindowPos(this->main_wnd, 0, 0, 0, w, h, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER | SWP_NOMOVE);
} else { } else {
int x = (GetSystemMetrics(SM_CXSCREEN) - w) / 2; int x = (GetSystemMetrics(SM_CXSCREEN) - w) / 2;
int y = (GetSystemMetrics(SM_CYSCREEN) - h) / 2; int y = (GetSystemMetrics(SM_CYSCREEN) - h) / 2;
@ -298,16 +231,16 @@ bool VideoDriver_Win32Base::MakeWindow(bool full_screen)
char window_title[64]; char window_title[64];
seprintf(window_title, lastof(window_title), "OpenTTD %s", _openttd_revision); 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); this->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"); if (this->main_wnd == nullptr) usererror("CreateWindow failed");
ShowWindow(_wnd.main_wnd, showstyle); ShowWindow(this->main_wnd, showstyle);
} }
} }
BlitterFactory::GetCurrentBlitter()->PostResize(); BlitterFactory::GetCurrentBlitter()->PostResize();
GameSizeChanged(); // invalidate all windows, force redraw GameSizeChanged();
return true; // the request succeeded return true;
} }
/* static */ void VideoDriver_Win32Base::PaintThreadThunk(VideoDriver_Win32Base *drv) /* 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; std::unique_lock<std::recursive_mutex> lock;
if (_draw_mutex != nullptr) lock = std::unique_lock<std::recursive_mutex>(*_draw_mutex); 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.width = _wnd.width_org = w;
_wnd.height = _wnd.height_org = h; _wnd.height = _wnd.height_org = h;
@ -1108,9 +1041,9 @@ void VideoDriver_Win32Base::EditBoxLostFocus()
std::unique_lock<std::recursive_mutex> lock; std::unique_lock<std::recursive_mutex> lock;
if (_draw_mutex != nullptr) lock = std::unique_lock<std::recursive_mutex>(*_draw_mutex); if (_draw_mutex != nullptr) lock = std::unique_lock<std::recursive_mutex>(*_draw_mutex);
CancelIMEComposition(_wnd.main_wnd); CancelIMEComposition(this->main_wnd);
SetCompositionPos(_wnd.main_wnd); SetCompositionPos(this->main_wnd);
SetCandidatePos(_wnd.main_wnd); SetCandidatePos(this->main_wnd);
} }
Dimension VideoDriver_Win32Base::GetScreenSize() const Dimension VideoDriver_Win32Base::GetScreenSize() const
@ -1139,14 +1072,14 @@ float VideoDriver_Win32Base::GetDPIScale()
UINT cur_dpi = 0; 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. */ /* 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. */ /* Per monitor is supported since Windows 8.1. */
UINT dpiX, dpiY; 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. cur_dpi = dpiX; // X and Y are always identical.
} }
} }
@ -1182,7 +1115,7 @@ const char *VideoDriver_Win32GDI::Start(const StringList &param)
RegisterWndClass(); RegisterWndClass();
MakePalette(); this->MakePalette();
FindResolutions(); FindResolutions();
@ -1204,9 +1137,9 @@ const char *VideoDriver_Win32GDI::Start(const StringList &param)
void VideoDriver_Win32GDI::Stop() void VideoDriver_Win32GDI::Stop()
{ {
DeleteObject(_wnd.gdi_palette); DeleteObject(this->gdi_palette);
DeleteObject(_wnd.dib_sect); DeleteObject(this->dib_sect);
DestroyWindow(_wnd.main_wnd); DestroyWindow(this->main_wnd);
if (_wnd.fullscreen) ChangeDisplaySettings(nullptr, 0); if (_wnd.fullscreen) ChangeDisplaySettings(nullptr, 0);
MyShowCursor(true); MyShowCursor(true);
@ -1232,11 +1165,11 @@ bool VideoDriver_Win32GDI::AllocateBackingStore(int w, int h, bool force)
bi->bmiHeader.biBitCount = bpp; bi->bmiHeader.biBitCount = bpp;
bi->bmiHeader.biCompression = BI_RGB; 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); HDC dc = GetDC(0);
_wnd.dib_sect = CreateDIBSection(dc, bi, DIB_RGB_COLORS, (VOID **)&_wnd.buffer_bits, nullptr, 0); this->dib_sect = CreateDIBSection(dc, bi, DIB_RGB_COLORS, (VOID **)&_wnd.buffer_bits, nullptr, 0);
if (_wnd.dib_sect == nullptr) usererror("CreateDIBSection failed"); if (this->dib_sect == nullptr) usererror("CreateDIBSection failed");
ReleaseDC(0, dc); ReleaseDC(0, dc);
_screen.width = w; _screen.width = w;
@ -1253,10 +1186,46 @@ bool VideoDriver_Win32GDI::AfterBlitterChange()
return this->AllocateBackingStore(_screen.width, _screen.height, true) && this->MakeWindow(_fullscreen); 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) void VideoDriver_Win32GDI::PaletteChanged(HWND hWnd)
{ {
HDC hDC = GetWindowDC(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); UINT nChanged = RealizePalette(hDC);
SelectPalette(hDC, hOldPalette, TRUE); SelectPalette(hDC, hOldPalette, TRUE);
@ -1270,18 +1239,18 @@ void VideoDriver_Win32GDI::Paint()
if (IsEmptyRect(_dirty_rect)) return; if (IsEmptyRect(_dirty_rect)) return;
HDC dc = GetDC(_wnd.main_wnd); HDC dc = GetDC(this->main_wnd);
HDC dc2 = CreateCompatibleDC(dc); HDC dc2 = CreateCompatibleDC(dc);
HBITMAP old_bmp = (HBITMAP)SelectObject(dc2, _wnd.dib_sect); HBITMAP old_bmp = (HBITMAP)SelectObject(dc2, this->dib_sect);
HPALETTE old_palette = SelectPalette(dc, _wnd.gdi_palette, FALSE); HPALETTE old_palette = SelectPalette(dc, this->gdi_palette, FALSE);
if (_cur_palette.count_dirty != 0) { if (_cur_palette.count_dirty != 0) {
Blitter *blitter = BlitterFactory::GetCurrentBlitter(); Blitter *blitter = BlitterFactory::GetCurrentBlitter();
switch (blitter->UsePaletteAnimation()) { switch (blitter->UsePaletteAnimation()) {
case Blitter::PALETTE_ANIMATION_VIDEO_BACKEND: 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; break;
case Blitter::PALETTE_ANIMATION_BLITTER: case Blitter::PALETTE_ANIMATION_BLITTER:
@ -1302,7 +1271,7 @@ void VideoDriver_Win32GDI::Paint()
SelectObject(dc2, old_bmp); SelectObject(dc2, old_bmp);
DeleteDC(dc2); DeleteDC(dc2);
ReleaseDC(_wnd.main_wnd, dc); ReleaseDC(this->main_wnd, dc);
_dirty_rect = {}; _dirty_rect = {};
} }
@ -1325,3 +1294,23 @@ void VideoDriver_Win32GDI::PaintThread()
_draw_signal->wait(*_draw_mutex); _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. */ /** Base class for Windows video drivers. */
class VideoDriver_Win32Base : public VideoDriver { class VideoDriver_Win32Base : public VideoDriver {
public: public:
VideoDriver_Win32Base() : main_wnd(nullptr) {}
void MakeDirty(int left, int top, int width, int height) override; void MakeDirty(int left, int top, int width, int height) override;
void MainLoop() override; void MainLoop() override;
@ -32,6 +34,8 @@ public:
void EditBoxLostFocus() override; void EditBoxLostFocus() override;
protected: protected:
HWND main_wnd; ///< Handle to system window.
Dimension GetScreenSize() const override; Dimension GetScreenSize() const override;
float GetDPIScale() override; float GetDPIScale() override;
void InputLoop() override; void InputLoop() override;
@ -58,6 +62,8 @@ private:
/** The GDI video driver for windows. */ /** The GDI video driver for windows. */
class VideoDriver_Win32GDI : public VideoDriver_Win32Base { class VideoDriver_Win32GDI : public VideoDriver_Win32Base {
public: public:
VideoDriver_Win32GDI() : dib_sect(nullptr), gdi_palette(nullptr) {}
const char *Start(const StringList &param) override; const char *Start(const StringList &param) override;
void Stop() override; void Stop() override;
@ -67,11 +73,21 @@ public:
const char *GetName() const override { return "win32"; } const char *GetName() const override { return "win32"; }
protected: protected:
HBITMAP dib_sect; ///< System bitmap object referencing our rendering buffer.
HPALETTE gdi_palette; ///< Palette object for 8bpp blitter.
void Paint() override; void Paint() override;
void PaintThread() override; void PaintThread() override;
bool AllocateBackingStore(int w, int h, bool force = false) override; bool AllocateBackingStore(int w, int h, bool force = false) override;
void PaletteChanged(HWND hWnd) 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. */ /** The factory for Windows' video driver. */