static bool bplcon0_interlace_seen;
static int scandoubled_line;
static bool vsync_rendered, frame_rendered, frame_shown;
-static float vsynctimeperline;
+static int vsynctimeperline;
static int frameskiptime;
static bool genlockhtoggle;
static bool genlockvtoggle;
compute_vsynctime ();
- hblank_hz = (double)(currprefs.ntscmode ? CHIPSET_CLOCK_NTSC : CHIPSET_CLOCK_PAL) / (maxhpos + (islinetoggle() ? 0.5 : 0));
+ hblank_hz = (currprefs.ntscmode ? CHIPSET_CLOCK_NTSC : CHIPSET_CLOCK_PAL) / (maxhpos + (islinetoggle() ? 0.5 : 0));
write_log (_T("%s mode%s%s V=%.4fHz H=%0.4fHz (%dx%d+%d) IDX=%d (%s) D=%d RTG=%d/%d\n"),
isntsc ? _T("NTSC") : _T("PAL"),
vsynctimeperline = 1;
if (0 || (log_vsync & 2)) {
- write_log (_T("%06d %.2f/%06d %03d%%\n"), t, vsynctimeperline, vsynctimebase, t * 100 / vsynctimebase);
+ write_log (_T("%06d %06d/%06d %03d%%\n"), t, vsynctimeperline, vsynctimebase, t * 100 / vsynctimebase);
}
frame_shown = true;
vsyncmaxtime = curr_time + max;
if (0)
- write_log (_T("%06d:%06d/%06d\n"), adjust, vsynctimeperline, vstb);
+ write_log (_T("%06d:%06d/%06d %d %d\n"), adjust, vsynctimeperline, vstb, max, maxvpos_display);
} else {
// low latency vsync
+#define LLV_DEBUG 0
+
static bool sync_timeout_check(frame_time_t max)
{
+#if LLV_DEBUG
+ return true;
+#else
frame_time_t rpt = read_processor_time();
return (int)rpt - (int)max <= 0;
+#endif
}
extern int busywait;
return;
int diff = vsync_hblank / (nextline - currline);
int us = 1000000 / diff;
- if (us < 2100) { // less than 2ms
+ if (us < 1300) { // spin if less than 1.3ms
target_spin(nextline - currline - 1);
return;
}
cpu_sleep_millis(1);
}
+static void linesync_first_last_line(int *first, int *last)
+{
+ *first = minfirstline;
+ *last = maxvpos_display;
+}
+
static bool linesync_beam_single(void)
{
frame_time_t maxtime = read_processor_time() + 2 * vsynctimebase;
bool was_syncline = is_syncline != 0;
is_syncline = 0;
- if (vpos == 0 && !was_syncline) {
+ if (vpos == 0) {
+ int firstline, lastline;
+ linesync_first_last_line(&firstline, &lastline);
+
display_slices = currprefs.gfx_display_sections;
if (display_slices <= 0)
display_slices = 1;
display_slice_cnt = 0;
vsyncnextscanline = vsync_activeheight / display_slices + 1;
- display_slice_lines = (maxvpos_display - minfirstline) / display_slices + 1;
- nextwaitvpos = minfirstline + display_slice_lines;
+ display_slice_lines = (lastline - firstline) / display_slices + 1;
+ nextwaitvpos = firstline + display_slice_lines;
if (display_slices <= 1)
nextwaitvpos = maxvpos_display + 1;
if (display_slices <= 2 && vsyncnextscanline > vsync_activeheight * 2 / 3)
frame_shown = true;
}
+ if (!display_slices)
+ return false;
+
if (vpos >= nextwaitvpos || is_last_line()) {
if (display_slice_cnt == 0) {
is_syncline = 0;
if (vpos == 0 && !was_syncline) {
+ int firstline, lastline;
+ linesync_first_last_line(&firstline, &lastline);
+
display_slices = currprefs.gfx_display_sections;
if (!display_slices)
display_slices = 1;
display_slice_cnt = 0;
vsyncnextscanline = vsync_activeheight / display_slices + 1;
vsyncnextscanline_add = vsync_activeheight / display_slices;
- display_slice_lines = (maxvpos_display - minfirstline) / display_slices + 1;
- nextwaitvpos = minfirstline + display_slice_lines + display_slice_lines / 2;
+ display_slice_lines = (lastline - firstline) / display_slices + 1;
+ nextwaitvpos = firstline + display_slice_lines + display_slice_lines / 2;
if (display_slices <= 1)
- nextwaitvpos = maxvpos_display + 1;
+ nextwaitvpos = lastline + 1;
if (display_slices <= 2 && vsyncnextscanline > vsync_activeheight * 2 / 3)
vsyncnextscanline = vsync_activeheight * 2 / 3;
frame_shown = true;
}
+ if (!display_slices)
+ return false;
+
if (is_last_line()) {
if (!was_syncline && !display_rendered) {
return 0;
}
scanlinesleep(vp, vsyncnextscanline);
+#if LLV_DEBUG
+ write_log(_T("1:%d:%d:%d:%d."), vpos, vp, nextwaitvpos, vsyncnextscanline);
+#endif
}
do_display_slice();
input_read_done = true;
display_slice_cnt = -1;
display_rendered = false;
+#if LLV_DEBUG
+ write_log("\n");
+#endif
} else if (vpos >= nextwaitvpos) {
return 0;
}
target_spin(0);
+#if LLV_DEBUG
+ write_log(_T("2:%d:%d:%d:%d."), vpos, vp, nextwaitvpos, vsyncnextscanline);
+#endif
}
do_display_slice();
display_rendered = false;
if (vp == -1) {
maybe_process_pull_audio();
target_spin(0);
+#if LLV_DEBUG
+ write_log(_T("3:%d:%d:%d:%d."), vpos, vp, nextwaitvpos, vsyncnextscanline);
+#endif
continue;
}
if (vp < 0 || vp >= vsyncnextscanline)
return 0;
}
scanlinesleep(vp, vsyncnextscanline);
+#if LLV_DEBUG
+ write_log(_T("4:%d:%d:%d:%d."), vpos, vp, nextwaitvpos, vsyncnextscanline);
+#endif
}
do_display_slice();
input_read_done = true;
}
nextwaitvpos += display_slice_lines;
display_slice_cnt++;
+#if LLV_DEBUG
+ write_log("\n");
+#endif
}
+
return input_read_done;
}
extern void target_quit (void);
extern void target_restart (void);
extern void target_getdate(int *y, int *m, int *d);
+extern void target_cpu_speed(void);
extern bool get_plugin_path (TCHAR *out, int size, const TCHAR *path);
extern void stripslashes (TCHAR *p);
extern void fixtrailing (TCHAR *p);
write_log(_T("\n"));
set_cpu_caches (true);
+ target_cpu_speed();
}
#define CYCLES_DIV 8192
currprefs.m68k_speed = changed_prefs.m68k_speed;
currprefs.m68k_speed_throttle = changed_prefs.m68k_speed_throttle;
update_68k_cycles();
+ target_cpu_speed();
}
cpu_prefs_changed_flag = 0;
}
}
}
+bool xD3D_getscanline(int *scanline, bool *invblank)
+{
+ struct d3dstruct *d3d = &d3ddata[0];
+ HRESULT hr;
+ D3DRASTER_STATUS rt;
+
+ if (!isd3d(d3d))
+ return false;
+ if (d3d->d3dswapchain)
+ hr = d3d->d3dswapchain->GetRasterStatus(&rt);
+ else
+ hr = d3d->d3ddev->GetRasterStatus(0, &rt);
+ if (FAILED(hr))
+ return false;
+ *scanline = rt.ScanLine;
+ *invblank = rt.InVBlank != FALSE;
+ return true;
+}
+
void d3d9_select(void)
{
D3D_free = xD3D_free;
D3D_run = NULL;
D3D_debug = xD3D_debug;
D3D_led = NULL;
+ D3D_getscanline = xD3D_getscanline;
}
#endif
extern void(*D3D_run)(int);
extern int(*D3D_debug)(int, int);
extern void(*D3D_led)(int, int, int);
+extern bool(*D3D_getscanline)(int*, bool*);
extern LPDIRECT3DSURFACE9 D3D_capture(int, int*,int*,int*);
extern bool D3D11_capture(int, void**,int*, int*,int*);
void(*D3D_run)(int);
int(*D3D_debug)(int, int);
void(*D3D_led)(int, int, int);
+bool(*D3D_getscanline)(int*, bool*);
static HMODULE hd3d11, hdxgi, hd3dcompiler, dwmapi;
D3D_run = xD3D11_run;
D3D_debug = xD3D11_debug;
D3D_led = xD3D11_led;
+ D3D_getscanline = NULL;
}
void d3d_select(struct uae_prefs *p)
int target_get_display_scanline(int displayindex)
{
- if (!pD3DKMTGetScanLine)
- return -10;
- D3DKMT_GETSCANLINE sl = { 0 };
- struct MultiDisplay *md = displayindex < 0 ? getdisplay(&currprefs) : &Displays[displayindex];
- if (!md->HasAdapterData)
- return -11;
- sl.VidPnSourceId = md->VidPnSourceId;
- sl.hAdapter = md->AdapterHandle;
- NTSTATUS status = pD3DKMTGetScanLine(&sl);
- if (status == STATUS_SUCCESS) {
- if (sl.InVerticalBlank)
- return -1;
- return sl.ScanLine;
- } else {
- if ((int)status > 0)
- return -(int)status;
- return status;
+ if (pD3DKMTGetScanLine) {
+ D3DKMT_GETSCANLINE sl = { 0 };
+ struct MultiDisplay *md = displayindex < 0 ? getdisplay(&currprefs) : &Displays[displayindex];
+ if (!md->HasAdapterData)
+ return -11;
+ sl.VidPnSourceId = md->VidPnSourceId;
+ sl.hAdapter = md->AdapterHandle;
+ NTSTATUS status = pD3DKMTGetScanLine(&sl);
+ if (status == STATUS_SUCCESS) {
+ if (sl.InVerticalBlank)
+ return -1;
+ return sl.ScanLine;
+ } else {
+ if ((int)status > 0)
+ return -(int)status;
+ return status;
+ }
+ return -12;
+ } else if (D3D_getscanline) {
+ int scanline;
+ bool invblank;
+ if (D3D_getscanline(&scanline, &invblank)) {
+ if (invblank)
+ return -1;
+ return scanline;
+ }
+ return -14;
}
- return -12;
+ return -13;
}
typedef LONG(CALLBACK* QUERYDISPLAYCONFIG)(UINT32, UINT32*, DISPLAYCONFIG_PATH_INFO*, UINT32*, DISPLAYCONFIG_MODE_INFO*, DISPLAYCONFIG_TOPOLOGY_ID*);
return 0;
}
+static void display_vblank_thread_kill(void)
+{
+ if (waitvblankthread_mode == 2) {
+ waitvblankthread_mode = 0;
+ while (waitvblankthread_mode != -1) {
+ Sleep(10);
+ }
+ waitvblankthread_mode = 0;
+ CloseHandle(waitvblankevent);
+ waitvblankevent = NULL;
+ }
+ wait_vblank_display = NULL;
+}
+
+static void display_vblank_thread(struct AmigaMonitor *mon)
+{
+ struct amigadisplay *ad = &adisplays[mon->monitor_id];
+ struct apmode *ap = ad->picasso_on ? &currprefs.gfx_apmode[1] : &currprefs.gfx_apmode[0];
+
+ if (currprefs.m68k_speed >= 0) {
+ display_vblank_thread_kill();
+ return;
+ }
+ // It seems some Windows 7 drivers hang if D3DKMTWaitForVerticalBlankEvent()
+ // and D3DKMTGetScanLine() is used simultaneously.
+ if (os_win8 && ap->gfx_vsyncmode && pD3DKMTWaitForVerticalBlankEvent && wait_vblank_display->HasAdapterData) {
+ waitvblankevent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ waitvblankthread_mode = 1;
+ unsigned int th;
+ _beginthreadex(NULL, 0, waitvblankthread, 0, 0, &th);
+ }
+}
+
+void target_cpu_speed(void)
+{
+ display_vblank_thread(&AMonitors[0]);
+}
+
extern void target_calibrate_spin(void);
static void display_param_init(struct AmigaMonitor *mon)
{
if (!wait_vblank_display || !wait_vblank_display->HasAdapterData) {
write_log(_T("Selected display mode does not have adapter data!\n"));
}
-
- if (ap->gfx_vsyncmode && pD3DKMTWaitForVerticalBlankEvent && wait_vblank_display->HasAdapterData) {
- waitvblankevent = CreateEvent(NULL, FALSE, FALSE, NULL);
- waitvblankthread_mode = 1;
- unsigned int th;
- _beginthreadex(NULL, 0, waitvblankthread, 0, 0, &th);
- }
Sleep(10);
target_calibrate_spin();
-}
-
-static void display_param_free(void)
-{
- if (waitvblankthread_mode == 2) {
- waitvblankthread_mode = 0;
- while (waitvblankthread_mode != -1) {
- Sleep(10);
- }
- waitvblankthread_mode = 0;
- CloseHandle(waitvblankevent);
- waitvblankevent = NULL;
- }
- wait_vblank_display = NULL;
+ display_vblank_thread(mon);
}
const TCHAR *target_get_display_name (int num, bool friendlyname)
{
mon->screen_is_initialized = 0;
if (!mon->monitor_id) {
- display_param_free();
+ display_vblank_thread_kill();
#ifdef AVIOUTPUT
AVIOutput_Restart();
#endif