if (vsyncnextstep != 1) {
vsyncnextstep = 1;
do_render_slice(-1, 0, vpos);
+ // wait until out of vblank
while (!currprefs.turbo_emulation && sync_timeout_check(maxtime)) {
maybe_process_pull_audio();
vp = target_get_display_scanline(-1);
if (vsyncnextstep != 2) {
vsyncnextstep = 2;
vsync_clear();
+ // wait until second half of display
while (!currprefs.turbo_emulation && sync_timeout_check(maxtime)) {
maybe_process_pull_audio();
vp = target_get_display_scanline(-1);
- if (vp >= vsync_activeheight - 1 || vp < 0)
+ if (vp >= vsync_activeheight / 2)
break;
if (currprefs.m68k_speed < 0 && !was_syncline) {
is_syncline = -2;
is_syncline_end = vsync_activeheight - 1;
return 0;
}
- scanlinesleep(vp, vsync_activeheight - 1);
+ scanlinesleep(vp, vsync_activeheight / 2);
}
}
if (vsyncnextstep != 3) {
vsyncnextstep = 3;
+ // wait until end of display (or start of next field)
+ while (!currprefs.turbo_emulation && sync_timeout_check(maxtime)) {
+ maybe_process_pull_audio();
+ vp = target_get_display_scanline(-1);
+ if (vp >= vsync_activeheight - 1 || vp < vsync_activeheight / 2)
+ break;
+ if (currprefs.m68k_speed < 0 && !was_syncline) {
+ is_syncline = -2;
+ is_syncline_end = vsync_activeheight - 1;
+ return 0;
+ }
+ scanlinesleep(vp, vsync_activeheight - 1);
+ }
+ }
+ if (vsyncnextstep != 4) {
+ vsyncnextstep = 4;
do_display_slice();
frame_rendered = true;
frame_shown = true;
+ // wait until first half of display
while (!currprefs.turbo_emulation && sync_timeout_check(maxtime)) {
maybe_process_pull_audio();
vp = target_get_display_scanline(-1);
linesync_first_last_line(&firstline, &lastline);
display_slices = currprefs.gfx_display_sections;
- if (!display_slices)
+ if (display_slices <= 0)
display_slices = 1;
display_slice_cnt = 0;
vsyncnextscanline = vsync_activeheight / display_slices + 1;
}
// flip slightly early because flip regularly gets delayed if done during vblank
- int lastflipline = vsync_activeheight - vsyncnextscanline_add / 3;
+ int lastflipline = vsync_activeheight - vsyncnextscanline_add / 5;
while (sync_timeout_check(maxtime)) {
int vp = target_get_display_scanline(-1);
maybe_process_pull_audio();
return -1;
}
+static volatile int waitvblankthread_mode;
+HANDLE waitvblankevent;
+static frame_time_t wait_vblank_timestamp;
+static MultiDisplay *wait_vblank_display;
+static volatile bool vsync_active;
+static bool scanlinecalibrating;
+
typedef NTSTATUS(CALLBACK* D3DKMTOPENADAPTERFROMHDC)(D3DKMT_OPENADAPTERFROMHDC*);
static D3DKMTOPENADAPTERFROMHDC pD3DKMTOpenAdapterFromHdc;
typedef NTSTATUS(CALLBACK* D3DKMTGETSCANLINE)(D3DKMT_GETSCANLINE*);
return -13;
}
-extern uae_u64 spincount;;
+extern uae_u64 spincount;
+bool calculated_scanline = 1;
+
int target_get_display_scanline(int displayindex)
{
- static uae_u64 lastrdtsc;
- static int lastvpos;
- if (spincount == 0 || currprefs.m68k_speed >= 0) {
- lastrdtsc = 0;
+ if (!scanlinecalibrating && calculated_scanline) {
+ static int lastline;
+ float diff = read_processor_time() - wait_vblank_timestamp;
+ if (diff < 0)
+ return -1;
+ int sl = (int)(diff * (vsync_activeheight + (vsync_totalheight - vsync_activeheight) / 10) * vsync_vblank / syncbase);
+ if (sl < 0)
+ sl = -1;
+ return sl;
+ } else {
+ static uae_u64 lastrdtsc;
+ static int lastvpos;
+ if (spincount == 0 || currprefs.m68k_speed >= 0) {
+ lastrdtsc = 0;
+ lastvpos = target_get_display_scanline2(displayindex);
+ return lastvpos;
+ }
+ uae_u64 v = __rdtsc();
+ if (lastrdtsc > v)
+ return lastvpos;
lastvpos = target_get_display_scanline2(displayindex);
+ lastrdtsc = __rdtsc() + spincount * 4;
return lastvpos;
}
- uae_u64 v = __rdtsc();
- if (lastrdtsc > v)
- return lastvpos;
- lastvpos = target_get_display_scanline2(displayindex);
- lastrdtsc = __rdtsc() + spincount * 4;
- return lastvpos;
}
typedef LONG(CALLBACK* QUERYDISPLAYCONFIG)(UINT32, UINT32*, DISPLAYCONFIG_PATH_INFO*, UINT32*, DISPLAYCONFIG_MODE_INFO*, DISPLAYCONFIG_TOPOLOGY_ID*);
return ret;
}
-static volatile int waitvblankthread_mode;
-HANDLE waitvblankevent;
-static frame_time_t wait_vblank_timestamp;
-static MultiDisplay *wait_vblank_display;
-static volatile bool vsync_active;
-
static unsigned int __stdcall waitvblankthread(void *dummy)
{
waitvblankthread_mode = 2;
- SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
+ SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
while (waitvblankthread_mode) {
D3DKMT_WAITFORVERTICALBLANKEVENT e = { 0 };
e.hAdapter = wait_vblank_display->AdapterHandle;
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;
- }
if (waitvblankthread_mode > 0)
return;
// It seems some Windows 7 drivers stall if D3DKMTWaitForVerticalBlankEvent()
// and D3DKMTGetScanLine() is used simultaneously.
- if (os_win8 && ap->gfx_vsyncmode && pD3DKMTWaitForVerticalBlankEvent && wait_vblank_display && wait_vblank_display->HasAdapterData) {
+ if ((calculated_scanline || os_win8) && ap->gfx_vsyncmode && pD3DKMTWaitForVerticalBlankEvent && wait_vblank_display && wait_vblank_display->HasAdapterData) {
waitvblankevent = CreateEvent(NULL, FALSE, FALSE, NULL);
waitvblankthread_mode = 1;
unsigned int th;
_beginthreadex(NULL, 0, waitvblankthread, 0, 0, &th);
+ } else {
+ calculated_scanline = 0;
}
}
write_log(_T("Selected display mode does not have adapter data!\n"));
}
Sleep(10);
+ scanlinecalibrating = true;
target_calibrate_spin();
+ scanlinecalibrating = false;
display_vblank_thread(mon);
}