--- a/src/video/win32_v.cpp Sat Jun 02 19:59:29 2007 +0000
+++ b/src/video/win32_v.cpp Sat Jul 14 19:42:58 2007 +0000
@@ -9,6 +9,7 @@
#include "../variables.h"
#include "../win32.h"
#include "../window.h"
+#include "../blitter/factory.hpp"
#include "win32_v.h"
#include <windows.h>
#include <tchar.h>
@@ -16,22 +17,18 @@
static struct {
HWND main_wnd;
HBITMAP dib_sect;
- Pixel *bitmap_bits;
- Pixel *buffer_bits;
- Pixel *alloced_bits;
+ void *buffer_bits;
HPALETTE gdi_palette;
int width;
int height;
int width_org;
int height_org;
bool fullscreen;
- bool double_size;
bool has_focus;
bool running;
} _wnd;
bool _force_full_redraw;
-bool _double_size;
bool _window_maximize;
uint _display_hz;
uint _fullscreen_bpp;
@@ -136,16 +133,11 @@
static void ClientSizeChanged(int w, int h)
{
- if (_wnd.double_size) {
- w /= 2;
- h /= 2;
- }
-
// allocate new dib section of the new size
if (AllocateDibSection(w, h)) {
// mark all palette colors dirty
_pal_first_dirty = 0;
- _pal_last_dirty = 255;
+ _pal_count_dirty = 255;
GameSizeChanged();
// redraw screen
@@ -209,6 +201,89 @@
}
}
+static void 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 defined(WINCE)
+ /* WinCE is always fullscreen */
+#else
+ if (full_screen) {
+ DEVMODE settings;
+
+ /* Make sure we are always at least the screen-depth of the blitter */
+ if (_fullscreen_bpp < BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth()) _fullscreen_bpp = BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth();
+
+ memset(&settings, 0, sizeof(settings));
+ settings.dmSize = sizeof(settings);
+ settings.dmFields =
+ (_fullscreen_bpp != 0 ? DM_BITSPERPEL : 0) |
+ DM_PELSWIDTH |
+ DM_PELSHEIGHT |
+ (_display_hz != 0 ? DM_DISPLAYFREQUENCY : 0);
+ settings.dmBitsPerPel = _fullscreen_bpp;
+ settings.dmPelsWidth = _wnd.width_org;
+ settings.dmPelsHeight = _wnd.height_org;
+ settings.dmDisplayFrequency = _display_hz;
+
+ if (ChangeDisplaySettings(&settings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) {
+ MakeWindow(false);
+ return;
+ }
+ } else if (_wnd.fullscreen) {
+ // restore display?
+ ChangeDisplaySettings(NULL, 0);
+ }
+#endif
+
+ {
+ RECT r;
+ DWORD style, showstyle;
+ int x, y, w, h;
+
+ showstyle = SW_SHOWNORMAL;
+ _wnd.fullscreen = full_screen;
+ if (_wnd.fullscreen) {
+ style = WS_POPUP;
+ SetRect(&r, 0, 0, _wnd.width_org, _wnd.height_org);
+ } else {
+ style = WS_OVERLAPPEDWINDOW;
+ /* On window creation, check if we were in maximize mode before */
+ if (_window_maximize) showstyle = SW_SHOWMAXIMIZED;
+ SetRect(&r, 0, 0, _wnd.width, _wnd.height);
+ }
+
+#if !defined(WINCE)
+ AdjustWindowRect(&r, style, FALSE);
+#endif
+ w = r.right - r.left;
+ h = r.bottom - r.top;
+ x = (GetSystemMetrics(SM_CXSCREEN) - w) / 2;
+ y = (GetSystemMetrics(SM_CYSCREEN) - h) / 2;
+
+ if (_wnd.main_wnd) {
+ ShowWindow(_wnd.main_wnd, SW_SHOWNORMAL); // remove maximize-flag
+ SetWindowPos(_wnd.main_wnd, 0, x, y, w, h, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER);
+ } else {
+ extern const char _openttd_revision[];
+ TCHAR Windowtitle[50];
+
+ _sntprintf(Windowtitle, sizeof(Windowtitle), _T("OpenTTD %s"), MB_TO_WIDE(_openttd_revision));
+
+ _wnd.main_wnd = CreateWindow(_T("OTTD"), Windowtitle, style, x, y, w, h, 0, 0, GetModuleHandle(NULL), 0);
+ if (_wnd.main_wnd == NULL) error("CreateWindow failed");
+ ShowWindow(_wnd.main_wnd, showstyle);
+ }
+ }
+ GameSizeChanged(); // invalidate all windows, force redraw
+}
+
static LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
static uint32 keycode = 0;
@@ -231,9 +306,25 @@
old_bmp = (HBITMAP)SelectObject(dc2, _wnd.dib_sect);
old_palette = SelectPalette(dc, _wnd.gdi_palette, FALSE);
- if (_pal_last_dirty != -1) {
- UpdatePalette(dc2, _pal_first_dirty, _pal_last_dirty - _pal_first_dirty + 1);
- _pal_last_dirty = -1;
+ if (_pal_count_dirty != 0) {
+ Blitter *blitter = BlitterFactoryBase::GetCurrentBlitter();
+
+ switch (blitter->UsePaletteAnimation()) {
+ case Blitter::PALETTE_ANIMATION_VIDEO_BACKEND:
+ UpdatePalette(dc2, _pal_first_dirty, _pal_count_dirty);
+ break;
+
+ case Blitter::PALETTE_ANIMATION_BLITTER:
+ blitter->PaletteAnimate(_pal_first_dirty, _pal_count_dirty);
+ break;
+
+ case Blitter::PALETTE_ANIMATION_NONE:
+ break;
+
+ default:
+ NOT_REACHED();
+ }
+ _pal_count_dirty = 0;
}
BitBlt(dc, 0, 0, _wnd.width, _wnd.height, dc2, 0, 0, SRCCOPY);
@@ -319,11 +410,6 @@
DrawMouseCursor();
}
- if (_wnd.double_size) {
- x /= 2;
- y /= 2;
- }
-
if (_cursor.fix_at) {
int dx = x - _cursor.pos.x;
int dy = y - _cursor.pos.y;
@@ -334,10 +420,6 @@
pt.x = _cursor.pos.x;
pt.y = _cursor.pos.y;
- if (_wnd.double_size) {
- pt.x *= 2;
- pt.y *= 2;
- }
ClientToScreen(hwnd, &pt);
SetCursorPos(pt.x, pt.y);
}
@@ -400,13 +482,6 @@
* WM_KEYDOWN only handles CTRL+ commands and special keys like VK_LEFT, etc. */
if (keycode == 0 || (keycode > WKC_PAUSE && GB(keycode, 13, 4) == 0)) return 0;
- if (keycode == ('D' | WKC_CTRL) && !_wnd.fullscreen) {
- _double_size ^= 1;
- _wnd.double_size = _double_size;
- ClientSizeChanged(_wnd.width, _wnd.height);
- MarkWholeScreenDirty();
- }
-
HandleKeypress(0 | (keycode << 16));
return 0;
}
@@ -455,16 +530,8 @@
w = r->right - r->left - (r2.right - r2.left);
h = r->bottom - r->top - (r2.bottom - r2.top);
- if (_wnd.double_size) {
- w /= 2;
- h /= 2;
- }
w = clamp(w, 64, MAX_SCREEN_WIDTH);
h = clamp(h, 64, MAX_SCREEN_HEIGHT);
- if (_wnd.double_size) {
- w *= 2;
- h *= 2;
- }
SetRect(&r2, 0, 0, w, h);
AdjustWindowRect(&r2, GetWindowLong(hwnd, GWL_STYLE), FALSE);
@@ -532,10 +599,34 @@
return 0;
}
- case WM_ACTIVATEAPP:
- _wnd.has_focus = (wParam != 0);
+ case WM_SETFOCUS:
+ _wnd.has_focus = true;
break;
+
+ case WM_KILLFOCUS:
+ _wnd.has_focus = false;
+ break;
+
+#if !defined(WINCE)
+ case WM_ACTIVATE: {
+ bool active = (LOWORD(wParam) != WA_INACTIVE);
+ bool minimized = (HIWORD(wParam) != 0);
+ if (_wnd.fullscreen) {
+ if (active && minimized) {
+ /* Restore the game window */
+ ShowWindow(hwnd, SW_RESTORE);
+ MakeWindow(true);
+ } else if (!active && !minimized) {
+ /* Minimise the window and restore desktop */
+ ShowWindow(hwnd, SW_MINIMIZE);
+ ChangeDisplaySettings(NULL, 0);
+ }
+ }
+ break;
+ }
}
+#endif
+
return DefWindowProc(hwnd, msg, wParam, lParam);
}
@@ -563,135 +654,41 @@
}
}
-static void MakeWindow(bool full_screen)
-{
- _fullscreen = full_screen;
-
- _wnd.double_size = _double_size && !full_screen;
-
- // recreate window?
- if ((full_screen || _wnd.fullscreen) && _wnd.main_wnd) {
- DestroyWindow(_wnd.main_wnd);
- _wnd.main_wnd = 0;
- }
-
-#if defined(WINCE)
- /* WinCE is always fullscreen */
-#else
- if (full_screen) {
- DEVMODE settings;
-
- memset(&settings, 0, sizeof(settings));
- settings.dmSize = sizeof(settings);
- settings.dmFields =
- (_fullscreen_bpp != 0 ? DM_BITSPERPEL : 0) |
- DM_PELSWIDTH |
- DM_PELSHEIGHT |
- (_display_hz != 0 ? DM_DISPLAYFREQUENCY : 0);
- settings.dmBitsPerPel = _fullscreen_bpp;
- settings.dmPelsWidth = _wnd.width_org;
- settings.dmPelsHeight = _wnd.height_org;
- settings.dmDisplayFrequency = _display_hz;
-
- if (ChangeDisplaySettings(&settings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) {
- MakeWindow(false);
- return;
- }
- } else if (_wnd.fullscreen) {
- // restore display?
- ChangeDisplaySettings(NULL, 0);
- }
-#endif
-
- {
- RECT r;
- DWORD style, showstyle;
- int x, y, w, h;
-
- showstyle = SW_SHOWNORMAL;
- _wnd.fullscreen = full_screen;
- if (_wnd.fullscreen) {
- style = WS_POPUP;
- SetRect(&r, 0, 0, _wnd.width_org, _wnd.height_org);
- } else {
- style = WS_OVERLAPPEDWINDOW;
- /* On window creation, check if we were in maximize mode before */
- if (_window_maximize) showstyle = SW_SHOWMAXIMIZED;
- SetRect(&r, 0, 0, _wnd.width, _wnd.height);
- }
-
-#if !defined(WINCE)
- AdjustWindowRect(&r, style, FALSE);
-#endif
- w = r.right - r.left;
- h = r.bottom - r.top;
- x = (GetSystemMetrics(SM_CXSCREEN) - w) / 2;
- y = (GetSystemMetrics(SM_CYSCREEN) - h) / 2;
-
- if (_wnd.main_wnd) {
- ShowWindow(_wnd.main_wnd, SW_SHOWNORMAL); // remove maximize-flag
- SetWindowPos(_wnd.main_wnd, 0, x, y, w, h, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER);
- } else {
- extern const char _openttd_revision[];
- TCHAR Windowtitle[50];
-
- _sntprintf(Windowtitle, sizeof(Windowtitle), _T("OpenTTD %s"), MB_TO_WIDE(_openttd_revision));
-
- _wnd.main_wnd = CreateWindow(_T("OTTD"), Windowtitle, style, x, y, w, h, 0, 0, GetModuleHandle(NULL), 0);
- if (_wnd.main_wnd == NULL) error("CreateWindow failed");
- ShowWindow(_wnd.main_wnd, showstyle);
- }
- }
- GameSizeChanged(); // invalidate all windows, force redraw
-}
-
static bool AllocateDibSection(int w, int h)
{
BITMAPINFO *bi;
HDC dc;
+ int bpp = BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth();
w = clamp(w, 64, MAX_SCREEN_WIDTH);
h = clamp(h, 64, MAX_SCREEN_HEIGHT);
+ if (bpp == 0) error("Can't use a blitter that blits 0 bpp for normal visuals");
+
if (w == _screen.width && h == _screen.height)
return false;
_screen.width = w;
- _screen.pitch = ALIGN(w, 4);
+ _screen.pitch = (bpp == 8) ? ALIGN(w, 4) : w;
_screen.height = h;
-
- if (_wnd.alloced_bits) {
- free(_wnd.alloced_bits);
- _wnd.alloced_bits = NULL;
- }
-
bi = (BITMAPINFO*)alloca(sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256);
memset(bi, 0, sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256);
bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- if (_wnd.double_size) {
- w = ALIGN(w, 4);
- _wnd.alloced_bits = _wnd.buffer_bits = (Pixel *)malloc(w * h * sizeof(Pixel));
- w *= 2;
- h *= 2;
- }
-
bi->bmiHeader.biWidth = _wnd.width = w;
bi->bmiHeader.biHeight = -(_wnd.height = h);
bi->bmiHeader.biPlanes = 1;
- bi->bmiHeader.biBitCount = 8;
+ bi->bmiHeader.biBitCount = BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth();
bi->bmiHeader.biCompression = BI_RGB;
if (_wnd.dib_sect) DeleteObject(_wnd.dib_sect);
dc = GetDC(0);
- _wnd.dib_sect = CreateDIBSection(dc, bi, DIB_RGB_COLORS, (VOID**)&_wnd.bitmap_bits, NULL, 0);
+ _wnd.dib_sect = CreateDIBSection(dc, bi, DIB_RGB_COLORS, (VOID**)&_wnd.buffer_bits, NULL, 0);
if (_wnd.dib_sect == NULL) error("CreateDIBSection failed");
ReleaseDC(0, dc);
- if (!_wnd.double_size) _wnd.buffer_bits = _wnd.bitmap_bits;
-
return true;
}
@@ -723,7 +720,7 @@
* Doesn't really matter since we don't pass a string anyways, but still
* a letdown */
for (i = 0; EnumDisplaySettingsA(NULL, i, &dm) != 0; i++) {
- if (dm.dmBitsPerPel == 8 && IS_INT_INSIDE(dm.dmPelsWidth, 640, MAX_SCREEN_WIDTH + 1) &&
+ if (dm.dmBitsPerPel == BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth() && IS_INT_INSIDE(dm.dmPelsWidth, 640, MAX_SCREEN_WIDTH + 1) &&
IS_INT_INSIDE(dm.dmPelsHeight, 480, MAX_SCREEN_HEIGHT + 1)) {
uint j;
@@ -754,8 +751,9 @@
SortResolutions(_num_resolutions);
}
+static FVideoDriver_Win32 iFVideoDriver_Win32;
-static const char *Win32GdiStart(const char * const *parm)
+const char *VideoDriver_Win32::Start(const char * const *parm)
{
memset(&_wnd, 0, sizeof(_wnd));
@@ -777,7 +775,7 @@
return NULL;
}
-static void Win32GdiStop()
+void VideoDriver_Win32::Stop()
{
DeleteObject(_wnd.gdi_palette);
DeleteObject(_wnd.dib_sect);
@@ -786,57 +784,28 @@
#if !defined(WINCE)
if (_wnd.fullscreen) ChangeDisplaySettings(NULL, 0);
#endif
- if (_wnd.double_size) {
- _cur_resolution[0] *= 2;
- _cur_resolution[1] *= 2;
- }
-
MyShowCursor(true);
}
-// simple upscaler by 2
-static void filter(int left, int top, int width, int height)
-{
- uint p = _screen.pitch;
- const Pixel *s = _wnd.buffer_bits + top * p + left;
- Pixel *d = _wnd.bitmap_bits + top * p * 4 + left * 2;
-
- for (; height > 0; height--) {
- int i;
-
- for (i = 0; i != width; i++) {
- d[i * 2] = d[i * 2 + 1] = d[i * 2 + p * 2] = d[i * 2 + 1 + p * 2] = s[i];
- }
- s += p;
- d += p * 4;
- }
-}
-
-static void Win32GdiMakeDirty(int left, int top, int width, int height)
+void VideoDriver_Win32::MakeDirty(int left, int top, int width, int height)
{
RECT r = { left, top, left + width, top + height };
- if (_wnd.double_size) {
- filter(left, top, width, height);
- r.left *= 2;
- r.top *= 2;
- r.right *= 2;
- r.bottom *= 2;
- }
InvalidateRect(_wnd.main_wnd, &r, FALSE);
}
static void CheckPaletteAnim()
{
- if (_pal_last_dirty == -1)
+ if (_pal_count_dirty == 0)
return;
InvalidateRect(_wnd.main_wnd, NULL, FALSE);
}
-static void Win32GdiMainLoop()
+void VideoDriver_Win32::MainLoop()
{
MSG mesg;
uint32 cur_ticks = GetTickCount();
+ uint32 last_cur_ticks = cur_ticks;
uint32 next_tick = cur_ticks + 30;
_wnd.running = true;
@@ -865,12 +834,11 @@
cur_ticks = GetTickCount();
if (cur_ticks >= next_tick || (_fast_forward && !_pause_game) || cur_ticks < prev_cur_ticks) {
+ _realtime_tick += cur_ticks - last_cur_ticks;
+ last_cur_ticks = cur_ticks;
next_tick = cur_ticks + 30;
_ctrl_pressed = _wnd.has_focus && GetAsyncKeyState(VK_CONTROL)<0;
_shift_pressed = _wnd.has_focus && GetAsyncKeyState(VK_SHIFT)<0;
-#ifdef _DEBUG
- _dbg_screen_rect = _wnd.has_focus && GetAsyncKeyState(VK_CAPITAL)<0;
-#endif
// determine which directional keys are down
if (_wnd.has_focus) {
@@ -906,7 +874,7 @@
}
}
-static bool Win32GdiChangeRes(int w, int h)
+bool VideoDriver_Win32::ChangeResolution(int w, int h)
{
_wnd.width = _wnd.width_org = w;
_wnd.height = _wnd.height_org = h;
@@ -916,16 +884,7 @@
return true;
}
-static void Win32GdiFullScreen(bool full_screen)
+void VideoDriver_Win32::ToggleFullscreen(bool full_screen)
{
MakeWindow(full_screen);
}
-
-const HalVideoDriver _win32_video_driver = {
- Win32GdiStart,
- Win32GdiStop,
- Win32GdiMakeDirty,
- Win32GdiMainLoop,
- Win32GdiChangeRes,
- Win32GdiFullScreen,
-};