From f04043f1f644f09d0934d507e810f3c9dd2c59a3 Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Sat, 14 May 2016 18:59:27 +0300 Subject: [PATCH] Variable refresh rate support improvements. --- od-win32/direct3d.cpp | 11 +++--- od-win32/win32gfx.cpp | 88 ++++++++++++++++++++++++++++++++++--------- 2 files changed, 77 insertions(+), 22 deletions(-) diff --git a/od-win32/direct3d.cpp b/od-win32/direct3d.cpp index b2fcbd06..7c455128 100644 --- a/od-win32/direct3d.cpp +++ b/od-win32/direct3d.cpp @@ -149,7 +149,7 @@ static int max_texture_w, max_texture_h; static int tin_w, tin_h, tout_w, tout_h, window_h, window_w; static int t_depth, dmult, dmultx; static int required_sl_texture_w, required_sl_texture_h; -static int vsync2, guimode, maxscanline; +static int vsync2, guimode, maxscanline, variablerefresh; static int resetcount; static double cursor_x, cursor_y; static bool cursor_v, cursor_scale; @@ -2382,6 +2382,7 @@ static const TCHAR *D3D_init2 (HWND ahwnd, int w_w, int w_h, int depth, int *fre modeex.Format = mode.Format; vsync2 = 0; + variablerefresh = ap.gfx_vsync < 0; int hzmult = 0; if (isfullscreen () > 0) { dpp.FullScreen_RefreshRateInHz = getrefreshrate (modeex.Width, modeex.Height); @@ -2615,7 +2616,7 @@ static const TCHAR *D3D_init2 (HWND ahwnd, int w_w, int w_h, int depth, int *fre if (forcedframelatency >= 0) hr = d3ddevex->SetMaximumFrameLatency (forcedframelatency); else if (dpp.PresentationInterval == D3DPRESENT_INTERVAL_IMMEDIATE && (v > 1 || !vsync)) - hr = d3ddevex->SetMaximumFrameLatency (vsync ? (hzmult < 0 && !ap.gfx_strobo ? 2 : 1) : 0); + hr = d3ddevex->SetMaximumFrameLatency (vsync ? (hzmult < 0 && !ap.gfx_strobo && !variablerefresh ? 2 : 1) : 0); if (FAILED (hr)) write_log (_T("%s: SetMaximumFrameLatency() failed: %s\n"), D3DHEAD, D3D_ErrorString (hr)); } @@ -3364,11 +3365,11 @@ void D3D_showframe (void) if (!isd3d ()) return; if (currprefs.turbo_emulation) { - if (!(dpp.PresentationInterval & D3DPRESENT_INTERVAL_IMMEDIATE) && wasstilldrawing_broken) { + if ((!(dpp.PresentationInterval & D3DPRESENT_INTERVAL_IMMEDIATE) || variablerefresh) && wasstilldrawing_broken) { static int frameskip; if (currprefs.turbo_emulation && frameskip-- > 0) return; - frameskip = 50; + frameskip = 10; } D3D_showframe2 (false); } else { @@ -3376,8 +3377,8 @@ void D3D_showframe (void) if (vsync2 == -1 && !currprefs.turbo_emulation) { D3D_showframe2 (true); } + flushgpu(true); } - flushgpu (true); } void D3D_showframe_special (int mode) diff --git a/od-win32/win32gfx.cpp b/od-win32/win32gfx.cpp index 7bb4a04e..0a5df00a 100644 --- a/od-win32/win32gfx.cpp +++ b/od-win32/win32gfx.cpp @@ -83,6 +83,7 @@ struct uae_filter *usedfilter; int scalepicasso; static double remembered_vblank; static volatile int vblankthread_mode, vblankthread_counter; +static int deskhz; struct winuae_currentmode { unsigned int flags; @@ -906,15 +907,17 @@ void sortdisplays (void) int w = GetSystemMetrics (SM_CXSCREEN); int h = GetSystemMetrics (SM_CYSCREEN); + int wv = GetSystemMetrics(SM_CXVIRTUALSCREEN); + int hv = GetSystemMetrics(SM_CYVIRTUALSCREEN); int b = 0; + + deskhz = 0; + HDC hdc = GetDC (NULL); if (hdc) { b = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES); ReleaseDC (NULL, hdc); } - write_log (_T("Desktop: W=%d H=%d B=%d. CXVS=%d CYVS=%d\n"), w, h, b, - GetSystemMetrics (SM_CXVIRTUALSCREEN), GetSystemMetrics (SM_CYVIRTUALSCREEN)); - md = Displays; while (md->monitorname) { md->DisplayModes = xmalloc (struct PicassoResolution, MAX_PICASSO_MODES); @@ -932,6 +935,10 @@ void sortdisplays (void) int idx2 = 0; while (md->DisplayModes[idx2].depth >= 0 && !found) { struct PicassoResolution *pr = &md->DisplayModes[idx2]; + if (dm.dmPelsWidth == w && dm.dmPelsHeight == h && dm.dmBitsPerPel == b) { + if (dm.dmDisplayFrequency > deskhz) + deskhz = dm.dmDisplayFrequency; + } if (pr->res.width == dm.dmPelsWidth && pr->res.height == dm.dmPelsHeight && pr->depth == dm.dmBitsPerPel / 8) { for (i = 0; pr->refresh[i]; i++) { if (pr->refresh[i] == dm.dmDisplayFrequency) { @@ -964,6 +971,8 @@ void sortdisplays (void) write_log (_T("%d display modes.\n"), i); md++; } + write_log(_T("Desktop: W=%d H=%d B=%d HZ=%d. CXVS=%d CYVS=%d\n"), w, h, b, deskhz, wv, hv); + } /* DirectX will fail with "Mode not supported" if we try to switch to a full @@ -1155,6 +1164,8 @@ bool show_screen_maybe (bool show) void show_screen_special (void) { + if (!screen_is_initialized) + return; if (currentmode->flags & DM_D3D) { gfx_lock(); D3D_showframe_special (1); @@ -1162,6 +1173,7 @@ void show_screen_special (void) } } static frame_time_t strobo_time; +static volatile bool strobo_active; static void CALLBACK blackinsertion_cb( UINT uTimerID, @@ -1171,22 +1183,44 @@ static void CALLBACK blackinsertion_cb( DWORD_PTR dw2 ) { - if (!screen_is_initialized) - return; - for (;;) { - frame_time_t ct = read_processor_time(); - if ((int)strobo_time - (int)ct <= 0 || (int)strobo_time - (int)ct > vsynctimebase / 2) { - break; + if (screen_is_initialized) { + while (strobo_active) { + frame_time_t ct = read_processor_time(); + int diff = (int)strobo_time - (int)ct; + if (diff < -vsynctimebase / 2) { + break; + } + if (diff <= 0) { + show_screen_special(); + break; + } + if (diff > vsynctimebase / 4) { + break; + } } } - if (!screen_is_initialized) - return; - show_screen_special(); + strobo_active = false; } +double target_adjust_vblank_hz(double hz) +{ + int maxrate; + if (!currprefs.lightboost_strobo) + return hz; + if (isfullscreen() > 0) { + maxrate = currentmode->freq; + } else { + maxrate = deskhz; + } + double nhz = hz * 2.0; + if (nhz >= maxrate - 1 && nhz < maxrate + 1) + hz -= 0.5; + return hz; +} void show_screen (int mode) { + strobo_active = false; gfx_lock(); if (mode == 2) { if (currentmode->flags & DM_D3D) { @@ -1201,13 +1235,33 @@ void show_screen (int mode) } if (currentmode->flags & DM_D3D) { struct apmode *ap = picasso_on ? &currprefs.gfx_apmode[1] : &currprefs.gfx_apmode[0]; - if (isfullscreen() > 0 && isvsync() == 0 && ap->gfx_strobo && ap->gfx_refreshrate > 80) { - //if (isvsync() == 0 && ap->gfx_strobo) { + if (ap->gfx_vsync < 0 && ap->gfx_strobo) { + double vblank = vblank_hz; + if (WIN32GFX_IsPicassoScreen()) { + if (currprefs.win32_rtgvblankrate > 0) + vblank = currprefs.win32_rtgvblankrate; + } + bool ok = true; int ratio = currprefs.lightboost_strobo_ratio; - int ms = 1000 / vblank_hz; + int ms = 1000 / vblank; int waitms = ms * ratio / 100 - 1; - strobo_time = read_processor_time() + vsynctimebase * ratio / 100; - timeSetEvent(waitms, 0, blackinsertion_cb, NULL, TIME_ONESHOT | TIME_CALLBACK_FUNCTION); + int maxrate; + if (isfullscreen() > 0) { + maxrate = currentmode->freq; + } else { + maxrate = deskhz; + } + if (maxrate > 0) { + double rate = vblank * 2.0; + rate *= ratio > 50 ? ratio / 50.0 : 50.0 / ratio; + if (rate > maxrate + 1.0) + ok = false; + } + if (ok) { + strobo_time = read_processor_time() + vsynctimebase * ratio / 100; + strobo_active = true; + timeSetEvent(waitms, 0, blackinsertion_cb, NULL, TIME_ONESHOT | TIME_CALLBACK_FUNCTION); + } } D3D_showframe(); #ifdef GFXFILTER -- 2.47.3