// low latency vsync
+static bool sync_timeout_check(frame_time_t max)
+{
+ frame_time_t rpt = read_processor_time();
+ return (int)rpt - (int)max <= 0;
+}
+
+extern int busywait;
static void scanlinesleep(int currline, int nextline)
{
if (currline < 0)
target_spin(nextline - currline - 1);
return;
}
+ if (busywait)
+ return;
cpu_sleep_millis(1);
}
static bool linesync_beam_single(void)
{
+ frame_time_t maxtime = read_processor_time() + 2 * vsynctimebase;
+
is_syncline = 0;
maybe_process_pull_audio();
if (is_last_line()) {
do_render_slice(-1, 0);
- while (!currprefs.turbo_emulation) {
+ while (!currprefs.turbo_emulation && sync_timeout_check(maxtime)) {
maybe_process_pull_audio();
target_spin(0);
int vp = target_get_display_scanline(-1);
break;
}
vsync_clear();
- while (!currprefs.turbo_emulation) {
+ while (!currprefs.turbo_emulation && sync_timeout_check(maxtime)) {
maybe_process_pull_audio();
int vp = target_get_display_scanline(-1);
if (vp >= vsync_activeheight - 1 || vp < 0)
break;
scanlinesleep(vp, vsync_activeheight - 1);
}
- while (!currprefs.turbo_emulation) {
+ while (!currprefs.turbo_emulation && sync_timeout_check(maxtime)) {
maybe_process_pull_audio();
target_spin(0);
int vp = target_get_display_scanline(-1);
static int display_slice_lines;
static int display_slices;
static bool display_rendered;
+ frame_time_t maxtime = read_processor_time() + 2 * vsynctimebase;
bool input_read_done = false;
bool was_syncline = is_syncline != 0;
display_rendered = true;
}
if (!currprefs.turbo_emulation) {
- while (!currprefs.turbo_emulation) {
+ while (!currprefs.turbo_emulation && sync_timeout_check(maxtime)) {
frame_time_t rpt = read_processor_time();
if ((int)rpt - (int)vsyncmintime >= 0 || (int)rpt - (int)vsyncmintime < -vsynctimebase * 2) {
vsyncmintime = rpt + vsynctimebase;
do_render_slice(0, display_slice_cnt);
display_rendered = true;
}
- for (;;) {
+ while(sync_timeout_check(maxtime)) {
int vp = target_get_display_scanline(-1);
if (vp == -1) {
maybe_process_pull_audio();
return input_read_done;
}
-
static bool linesync_beam_multi(void)
{
static int vsyncnextscanline;
static int display_slice_lines;
static int display_slices;
static bool display_rendered;
+ frame_time_t maxtime = read_processor_time() + 2 * vsynctimebase;
bool input_read_done = false;
bool was_syncline = is_syncline != 0;
do_render_slice(0, display_slice_cnt);
display_rendered = true;
}
- while (!currprefs.turbo_emulation) {
+ // if 2 slices: make sure we are out of vblank.
+ if (display_slices <= 2) {
+ while (!currprefs.turbo_emulation && sync_timeout_check(maxtime)) {
+ int vp = target_get_display_scanline(-1);
+ if (vp != -1)
+ break;
+ maybe_process_pull_audio();
+ target_spin(0);
+ }
+ vsync_clear();
+ }
+ while (!currprefs.turbo_emulation && sync_timeout_check(maxtime)) {
int vp = target_get_display_scanline(-1);
if (vp < 0 || vp >= vsyncnextscanline)
break;
do_render_slice(1, display_slice_cnt);
display_rendered = true;
- for (;;) {
+ for(;;) {
frame_time_t rpt = read_processor_time();
if ((int)rpt - (int)vsyncmintime >= 0 || (int)rpt - (int)vsyncmintime < -2 * vsynctimebase)
break;
target_spin(0);
}
vsyncmintime = read_processor_time() + vsynctimebase;
-
- while (!currprefs.turbo_emulation) {
- maybe_process_pull_audio();
- int vp = target_get_display_scanline(-1);
- if (vp < 0)
- break;
- scanlinesleep(vp, vsync_activeheight - 1);
- }
-
do_display_slice();
display_rendered = false;
input_read_done = true;
display_rendered = true;
}
- for (;;) {
+ while (sync_timeout_check(maxtime)) {
int vp = target_get_display_scanline(-1);
maybe_process_pull_audio();
if (vp < 0 || vp < vsync_activeheight / 2 || vp >= vsync_activeheight - 1)
do_render_slice(0, display_slice_cnt);
display_rendered = true;
}
- for(;;) {
+ while (sync_timeout_check(maxtime)) {
int vp = target_get_display_scanline(-1);
if (vp == -1) {
maybe_process_pull_audio();
if (currprefs.gfx_display_sections <= 1) {
linesync_beam_single();
} else {
- if (vsync_hblank >= 85 && currprefs.gfx_variable_sync)
+ if (vsync_hblank >= 85 && !currprefs.gfx_variable_sync)
linesync_beam_multi_dual();
else
linesync_beam_multi();
LUID AdapterLuid;
UINT VidPnSourceId;
UINT AdapterHandle;
+ bool HasAdapterData;
};
extern struct MultiDisplay Displays[MAX_DISPLAYS + 1];
int pissoff_value = 15000 * CYCLE_UNIT;
unsigned int fpucontrol;
int extraframewait, extraframewait2;
+int busywait;
extern FILE *debugfile;
extern int console_logging;
spincount = 0;
if (!ap->gfx_vsyncmode)
return;
+ if (busywait) {
+ write_log(_T("target_calibrate_spin() skipped\n"));
+ return;
+ }
+ write_log(_T("target_calibrate_spin() start\n"));
spincount = 0x800000000000;
for (int i = 0; i < 50; i++) {
for (;;) {
vp = target_get_display_scanline(-1);
+ if (vp <= -10)
+ goto fail;
if (vp >= 1 && vp < vsync_activeheight - 10)
break;
}
+ int vp3 = target_get_display_scanline(-1);
for (;;) {
int vp2 = target_get_display_scanline(-1);
+ if (vp2 <= -10)
+ goto fail;
if (vp2 == vp + 1)
break;
+ if (vp2 != vp)
+ goto trynext;
}
uae_u64 v1 = __rdtsc();
for (;;) {
int vp2 = target_get_display_scanline(-1);
+ if (vp2 <= -10)
+ goto fail;
if (vp2 == vp + 2) {
uae_u64 sc = __rdtsc() - v1;
if (spincount > sc)
if (vp2 != vp + 1)
break;
}
+trynext:;
}
if (spincount == 0x800000000000) {
write_log(_T("Spincount calculation error, spinloop not used.\n"), spincount);
} else {
write_log(_T("Spincount = %llu\n"), spincount);
}
+ return;
+fail:
+ write_log(_T("Scanline read failed: %d!\n"), vp);
+ spincount = 0;
}
int timeend (void)
return ret;
}
-bool quit_ok()
+bool quit_ok(void)
{
if (isfullscreen() > 0)
return true;
}
struct MultiDisplay *md = getdisplay (p);
- for (int i = 0; i < MAX_AMIGADISPLAYS; i++) {
- if (p->gfx_monitor[i].gfx_size_fs.special == WH_NATIVE) {
+ for (int j = 0; j < MAX_AMIGADISPLAYS; j++) {
+ if (p->gfx_monitor[j].gfx_size_fs.special == WH_NATIVE) {
int i;
for (i = 0; md->DisplayModes[i].depth >= 0; i++) {
if (md->DisplayModes[i].res.width == md->rect.right - md->rect.left &&
md->DisplayModes[i].res.height == md->rect.bottom - md->rect.top) {
- p->gfx_monitor[i].gfx_size_fs.width = md->DisplayModes[i].res.width;
- p->gfx_monitor[i].gfx_size_fs.height = md->DisplayModes[i].res.height;
+ p->gfx_monitor[j].gfx_size_fs.width = md->DisplayModes[i].res.width;
+ p->gfx_monitor[j].gfx_size_fs.height = md->DisplayModes[i].res.height;
+ write_log(_T("Native resolution: %dx%d\n"), p->gfx_monitor[j].gfx_size_fs.width, p->gfx_monitor[j].gfx_size_fs.height);
break;
}
}
- if (md->DisplayModes[i].depth < 0)
- p->gfx_monitor[i].gfx_size_fs.special = 0;
+ if (md->DisplayModes[i].depth < 0) {
+ p->gfx_monitor[j].gfx_size_fs.special = 0;
+ write_log(_T("Native resolution not found.\n"));
+ }
}
}
/* switch from 32 to 16 or vice versa if mode does not exist */
floppy_writemode = -1;
return 1;
}
+ if (!_tcscmp(arg, _T("busywait"))) {
+ busywait = 1;
+ return 1;
+ }
if (!np)
return 0;
static struct MultiDisplay *getdisplay2(struct uae_prefs *p, int index)
{
struct AmigaMonitor *mon = &AMonitors[0];
- int max;
+ static int max;
int display = index < 0 ? p->gfx_apmode[mon->screen_is_picasso ? APMODE_RTG : APMODE_NATIVE].gfx_display - 1 : index;
- max = 0;
- while (Displays[max].monitorname)
- max++;
- if (max == 0) {
- gui_message (_T("no display adapters! Exiting"));
- exit (0);
+ if (!max || (max > 0 && Displays[max].monitorname != NULL)) {
+ max = 0;
+ while (Displays[max].monitorname)
+ max++;
+ if (max == 0) {
+ gui_message(_T("no display adapters! Exiting"));
+ exit(0);
+ }
}
if (index >= 0 && display >= max)
return NULL;
}
struct MultiDisplay *getdisplay (struct uae_prefs *p)
{
- return getdisplay2 (p, -1);
+ return getdisplay2(p, -1);
}
void desktop_coords(int monid, int *dw, int *dh, int *ax, int *ay, int *aw, int *ah)
int target_get_display_scanline(int displayindex)
{
if (!pD3DKMTGetScanLine)
- return -2;
+ 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;
- if (pD3DKMTGetScanLine(&sl) == STATUS_SUCCESS) {
+ 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 -2;
+ return -12;
}
typedef LONG(CALLBACK* QUERYDISPLAYCONFIG)(UINT32, UINT32*, DISPLAYCONFIG_PATH_INFO*, UINT32*, DISPLAYCONFIG_MODE_INFO*, DISPLAYCONFIG_TOPOLOGY_ID*);
struct amigadisplay *ad = &adisplays[mon->monitor_id];
struct apmode *ap = ad->picasso_on ? &currprefs.gfx_apmode[1] : &currprefs.gfx_apmode[0];
- wait_vblank_display = getdisplay(&currprefs);
-
vsync_activeheight = mon->currentmode.current_height;
vsync_totalheight = vsync_activeheight * 1125 / 1080;
vsync_vblank = 0;
vsync_activeheight = mon->currentmode.current_height;
}
- if (ap->gfx_vsyncmode && pD3DKMTWaitForVerticalBlankEvent) {
+ wait_vblank_display = getdisplay(&currprefs);
+ 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;
if (hdc != NULL) {
D3DKMT_OPENADAPTERFROMHDC OpenAdapterData = { 0 };
OpenAdapterData.hDc = hdc;
- if (pD3DKMTOpenAdapterFromHdc(&OpenAdapterData) == STATUS_SUCCESS) {
+ NTSTATUS status = pD3DKMTOpenAdapterFromHdc(&OpenAdapterData);
+ if (status == STATUS_SUCCESS) {
md->AdapterLuid = OpenAdapterData.AdapterLuid;
md->VidPnSourceId = OpenAdapterData.VidPnSourceId;
md->AdapterHandle = OpenAdapterData.hAdapter;
+ md->HasAdapterData = true;
}
DeleteDC(hdc);
}
void vsync_clear(void)
{
vsync_active = false;
- ResetEvent(waitvblankevent);
+ if (waitvblankevent)
+ ResetEvent(waitvblankevent);
}
int vsync_isdone(frame_time_t *dt)