From 403152419da7f1aa4385441b6357543f4f49f80a Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Sun, 10 Jul 2011 17:00:00 +0300 Subject: [PATCH] 2330b3 --- cfgfile.cpp | 12 +++- custom.cpp | 54 ++++++++++------ include/options.h | 1 + include/xwin.h | 3 +- inputdevice.cpp | 2 +- od-win32/cloanto/RetroPlatformIPC.h | 98 ++++++++++++++++++++++------- od-win32/direct3d.cpp | 67 ++++++++++++++------ od-win32/direct3d.h | 3 +- od-win32/rp.cpp | 97 +++++++++++++++------------- od-win32/win32.h | 4 +- od-win32/win32gfx.cpp | 55 +++++++++++++--- od-win32/win32gfx.h | 1 - od-win32/win32gui.cpp | 21 ++++--- od-win32/winuaechangelog.txt | 5 ++ 14 files changed, 295 insertions(+), 128 deletions(-) diff --git a/cfgfile.cpp b/cfgfile.cpp index cd80da8b..4fe504bc 100644 --- a/cfgfile.cpp +++ b/cfgfile.cpp @@ -945,6 +945,8 @@ void cfgfile_save_options (struct zfile *f, struct uae_prefs *p, int type) _tcscat (s, L",vsync"); else if (cr->vsync == 0) _tcscat (s, L",nvsync"); + if (cr->rtg) + _tcscat (s, L",rtg"); if (cr->commands[0]) { _tcscat (s, L","); _tcscat (s, cr->commands); @@ -1900,7 +1902,8 @@ static int cfgfile_parse_host (struct uae_prefs *p, TCHAR *option, TCHAR *value) tmpbuf[sizeof tmpbuf / sizeof (TCHAR) - 1] = '\0'; int vert = -1, horiz = -1, lace = -1, ntsc = -1, framelength = -1, vsync = -1; - int locked = 0; + bool locked = false; + bool rtg = false; double rate = -1; TCHAR cmd[MAX_DPATH], label[16] = { 0 }; TCHAR *tmpp = tmpbuf; @@ -1933,7 +1936,7 @@ static int cfgfile_parse_host (struct uae_prefs *p, TCHAR *option, TCHAR *value) } } if (!_tcsnicmp (tmpp, L"locked", 4)) - locked = 1; + locked = true; if (!_tcsnicmp (tmpp, L"nlace", 5)) lace = 0; if (!_tcsnicmp (tmpp, L"lace", 4)) @@ -1950,6 +1953,8 @@ static int cfgfile_parse_host (struct uae_prefs *p, TCHAR *option, TCHAR *value) framelength = 1; if (!_tcsnicmp (tmpp, L"shf", 3)) framelength = 0; + if (!_tcsnicmp (tmpp, L"rtg", 3)) + rtg = true; tmpp = next; if (tmpp >= end) break; @@ -1972,7 +1977,8 @@ static int cfgfile_parse_host (struct uae_prefs *p, TCHAR *option, TCHAR *value) p->cr[i].lace = lace; p->cr[i].ntsc = ntsc; p->cr[i].vsync = vsync; - p->cr[i].locked = locked != 0; + p->cr[i].locked = locked; + p->cr[i].rtg = rtg; p->cr[i].framelength = framelength; p->cr[i].rate = rate; _tcscpy (p->cr[i].commands, cmd); diff --git a/custom.cpp b/custom.cpp index 42982cdf..9702252e 100644 --- a/custom.cpp +++ b/custom.cpp @@ -2876,17 +2876,18 @@ void init_hz (bool fullinit) reset_drawing (); } - if (!picasso_on) { - for (int i = 0; i < MAX_CHIPSET_REFRESH_TOTAL; i++) { - struct chipset_refresh *cr = &currprefs.cr[i]; - if ((cr->horiz < 0 || cr->horiz == maxhpos) && - (cr->vert < 0 || cr->vert == maxvpos_nom) && - (cr->ntsc < 0 || (cr->ntsc > 0 && isntsc) || (cr->ntsc == 0 && !isntsc)) && - (cr->lace < 0 || (cr->lace > 0 && islace) || (cr->lace == 0 && !islace)) && - (cr->framelength < 0 || (cr->framelength > 0 && lof_store) || (cr->framelength == 0 && !lof_store)) && - (cr->vsync < 0 || (cr->vsync > 0 && isvsync ()) || (cr->vsync == 0 && !isvsync ()))) { - double v = -1; - + for (int i = 0; i < MAX_CHIPSET_REFRESH_TOTAL; i++) { + struct chipset_refresh *cr = &currprefs.cr[i]; + if ((cr->horiz < 0 || cr->horiz == maxhpos) && + (cr->vert < 0 || cr->vert == maxvpos_nom) && + (cr->ntsc < 0 || (cr->ntsc > 0 && isntsc) || (cr->ntsc == 0 && !isntsc)) && + (cr->lace < 0 || (cr->lace > 0 && islace) || (cr->lace == 0 && !islace)) && + (cr->framelength < 0 || (cr->framelength > 0 && lof_store) || (cr->framelength == 0 && !lof_store)) && + ((cr->rtg && picasso_on) || (!cr->rtg && !picasso_on)) && + (cr->vsync < 0 || (cr->vsync > 0 && isvsync ()) || (cr->vsync == 0 && !isvsync ()))) { + double v = -1; + + if (!picasso_on) { if (isvsync ()) { if (i == CHIPSET_REFRESH_PAL || i == CHIPSET_REFRESH_NTSC) { if ((abs (vblank_hz - 50) < 1 || abs (vblank_hz - 60) < 1) && currprefs.gfx_avsync == 2 && currprefs.gfx_afullscreen > 0) { @@ -2909,11 +2910,18 @@ void init_hz (bool fullinit) if (v < 0) v = cr->rate; if (v > 0) { - changed_prefs.chipset_refreshrate = v; + changed_prefs.chipset_refreshrate = currprefs.chipset_refreshrate = v; cfgfile_parse_lines (&changed_prefs, cr->commands, -1); } - break; - } + } else { + if (cr->locked == false) + v = vblank_hz; + else + v = cr->rate; + changed_prefs.chipset_refreshrate = currprefs.chipset_refreshrate = v; + cfgfile_parse_lines (&changed_prefs, cr->commands, -1); + } + break; } } @@ -5044,26 +5052,29 @@ static void framewait (void) if (vs > 0) { vsyncmintime = vsynctime; - update_screen (); + render_screen (); + show_screen (); return; } else if (vs < 0) { vsyncmintime = vsynctime; + render_screen (); vsync_busywait (); - update_screen (); + show_screen (); return; } + render_screen (); for (;;) { double v = rpt_vsync () / (syncbase / 1000.0); if (v >= -4) break; sleep_millis (2); } - update_screen (); curr_time = start = read_processor_time (); while (rpt_vsync () < 0); curr_time = read_processor_time (); vsyncmintime = curr_time + vsynctime; idletime += read_processor_time() - start; + show_screen (); } static frame_time_t frametime2; @@ -5170,7 +5181,8 @@ static void vsync_handler_post (void) if ((long int)(curr_time - vsyncmintime) > 0 || rpt_did_reset) vsyncmintime = curr_time + vsynctime; rpt_did_reset = 0; - update_screen (); + render_screen (); + show_screen (); } else if (rpt_available) { framewait (); } @@ -5179,14 +5191,16 @@ static void vsync_handler_post (void) if (rpt_available && currprefs.m68k_speed == 0) { framewait (); } else { - update_screen (); + render_screen (); + show_screen (); } } #endif } else if (currprefs.m68k_speed == 0) { framewait (); } else { - update_screen (); + render_screen (); + show_screen (); } #if CUSTOM_DEBUG > 1 diff --git a/include/options.h b/include/options.h index cc109bfa..39a03ac7 100644 --- a/include/options.h +++ b/include/options.h @@ -143,6 +143,7 @@ enum { CP_GENERIC = 1, CP_CDTV, CP_CD32, CP_A500, CP_A500P, CP_A600, CP_A1000, struct chipset_refresh { bool locked; + bool rtg; int horiz; int vert; int lace; diff --git a/include/xwin.h b/include/xwin.h index a6ddf071..2c872f07 100644 --- a/include/xwin.h +++ b/include/xwin.h @@ -36,7 +36,8 @@ extern void flush_line (int); extern void flush_block (int, int); extern void flush_screen (int, int); extern void flush_clear_screen (void); -extern void update_screen (void); +extern bool render_screen (void); +extern void show_screen (void); extern int lockscr (int); extern void unlockscr (void); diff --git a/inputdevice.cpp b/inputdevice.cpp index d273d5cc..0c198843 100644 --- a/inputdevice.cpp +++ b/inputdevice.cpp @@ -1483,7 +1483,7 @@ static int mouseedge (void) static int melast_x, melast_y; static int isnonzero; - if (currprefs.input_magic_mouse == 0 || currprefs.input_tablet > 0) + if (currprefs.input_magic_mouse == 0 || currprefs.input_tablet > 0 || isfullscreen ()) return 0; if (magicmouse_ibase == 0xffffffff) return 0; diff --git a/od-win32/cloanto/RetroPlatformIPC.h b/od-win32/cloanto/RetroPlatformIPC.h index 50508276..7134d587 100644 --- a/od-win32/cloanto/RetroPlatformIPC.h +++ b/od-win32/cloanto/RetroPlatformIPC.h @@ -8,7 +8,7 @@ : License version 2 as published by the Free Software Foundation. Authors : os, mcb Created : 2007-08-27 13:55:49 - Updated : 2011-02-02 12:20:00 + Updated : 2011-07-07 00:04:00 Comment : RP Player interprocess communication include file *****************************************************************************/ @@ -17,9 +17,9 @@ #include -#define RPLATFORM_API_VER "1.4" +#define RPLATFORM_API_VER "1.5" #define RPLATFORM_API_VER_MAJOR 1 -#define RPLATFORM_API_VER_MINOR 4 +#define RPLATFORM_API_VER_MINOR 5 #define RPIPC_HostWndClass "RetroPlatformHost%s" #define RPIPC_GuestWndClass "RetroPlatformGuest%d" @@ -94,23 +94,28 @@ #define RP_FEATURE_STATE 0x00000400 // loading and saving of emulation state is supported (see RPIPCHM_SAVESTATE/RPIPCHM_LOADSTATE message) #define RP_FEATURE_SCANLINES 0x00000800 // scan lines video effect is available #define RP_FEATURE_DEVICEREADWRITE 0x00001000 // device read/write can be set at runtime on floppy and hard disks +#define RP_FEATURE_RESIZE_SUBPIXEL 0x00002000 // supports sub-pixel scaling of windowed and full-screen modes (i.e. not just integer multipliers like 1X, 2X, etc., but stretch to fill any desired pixel size) +#define RP_FEATURE_RESIZE_STRETCH 0x00004000 // supports "stretch to fill" (without preserving original ratio) in full-screen mode or with lTargetWidth and lTargetHeight set // Screen Modes #define RP_SCREENMODE_1X 0x00000000 // 1x window or full-screen mode ("CGA mode") #define RP_SCREENMODE_2X 0x00000001 // 2x window or full-screen mode ("VGA mode") #define RP_SCREENMODE_3X 0x00000002 // 3x window or full-screen mode ("triple CGA mode") #define RP_SCREENMODE_4X 0x00000003 // 4x window or full-screen mode ("double VGA mode") -#define RP_SCREENMODE_XX 0x000000FF // autoset maximum nX (integer n, preserve ratio) +#define RP_SCREENMODE_WW 0x000000FE // scale WindoW to lTargetWidth/lTargetHeight (default: maximum possible integer multiplication, no subpixel stretching, preserve ratio) +#define RP_SCREENMODE_XX 0x000000FF // autoset maximum nX (default: maximum possible integer multiplication, no subpixel stretching, preserve ratio) #define RP_SCREENMODE_MODEMASK 0x000000FF #define RP_SCREENMODE_FULLSCREEN_1 0x00000100 // full screen on primary (default) display #define RP_SCREENMODE_FULLSCREEN_2 0x00000200 // full screen on secondary display (fallback to 1 if unavailable) #define RP_SCREENMODE_DISPLAYMASK 0x0000FF00 -#define RP_SCREENMODE_FULLWINDOW 0x00010000 // use "full window" when in fullscreen (no gfx card full screen) +#define RP_SCREENMODE_FULLWINDOW 0x00010000 // use "full window" (desktop size) when in full screen (no gfx card full screen) #define RP_SCREENMODE_USETVM_NEVER 0x00000000 // never use TV modes #define RP_SCREENMODE_USETVM_ALWAYS 0x00020000 // always use TV modes #define RP_SCREENMODE_USETVM_AUTO 0x00040000 // use all available modes #define RP_SCREENMODE_USETVMMASK 0x00060000 #define RP_SCREENMODE_SCANLINES 0x00080000 // show video scan lines +#define RP_SCREENMODE_SUBPIXEL 0x00100000 // use sub-pixel (non-integer) scaling in full-screen = "XX" mode, or with lTargetWidth and lTargetHeight set (if not set may add black bars) +#define RP_SCREENMODE_STRETCH 0x00200000 // "stretch to fill" (do not preserve original ratio) in full-screen = "XX" mode, or with lTargetWidth and lTargetHeight set (if not set may add black bars) #define RP_SCREENMODE_DISPLAY(m) (((m) & RP_SCREENMODE_DISPLAYMASK) >> 8) // given a mode 'm' returns the display number (1-255) or 0 if full screen is not active #define RP_SCREENMODE_USETVM(m) ((m) & RP_SCREENMODE_USETVMMASK) // given a mode 'm' returns the RP_SCREENMODE_USETVM_* value in it (automatic display mode selection in full screen modes) #define RP_SCREENMODE_MODE(m) ((m) & RP_SCREENMODE_MODEMASK) // given a mode 'm' returns the #X mode @@ -119,35 +124,85 @@ #define RP_CLIPFLAGS_AUTOCLIP 0x00000001 // ignore all 4 Clip values (same as all values = -1) and use "smart" offset and size #define RP_CLIPFLAGS_NOCLIP 0x00000002 // ignore all 4 Clip values (same as all values = -1) and use 0:0 offset and maximum possible size (probably ugly, but good for adjusting clip area manually) -// Clip/Scale Examples // -// An Amiga game with known clip offset/size will have lClipLeft/Top/Width/Height set, and no RP_CLIPFLAGS. +// Integer vs. subpixel scaling, and stretching with or without original ratio +// +// By default, the guest is only expected to be able to scale (resize) the window by an integer number of times, e.g. 1X, 2X, 3X, etc., as indicated in RP_FEATURE_SCREEN... +// This means that when going to full-screen or full-window mode or a window mode with lTargetWidth and lTargetHeight set, the content will be an integer number of times the original, and surrounded by black bars if necessary. +// +// In a known-size target (e.g. full-screen), unless RP_SCREENMODE_SUBPIXEL or RP_SCREENMODE_STRETCH are set, there may be up to four black bars to fill any unused space. +// +// RP_SCREENMODE_SUBPIXEL (used only if RP_FEATURE_RESIZE_SUBPIXEL was set) allows for subpixel resize scenarios beyond integer 1X, 2X, etc. This is both in full-screen/window and in window mode. +// +// In a known-size target (e.g. full-screen), RP_SCREENMODE_SUBPIXEL allows for "stretch to fill" with black areas only on two sides out of four (e.g. 4:3 displayed on 16:9 will fill to the top and bottom, and have bars only on the left and right). +// +// RP_SCREENMODE_STRETCH (used only if RP_FEATURE_RESIZE_STRETCH was set) allows to break (not respect) the original screen ratio. +// +// In theory RP_SCREENMODE_STRETCH could be used alone (without RP_SCREENMODE_SUBPIXEL), but it probably doesn'd make practical sense. In any case, the theoretical result would be scaling with different integer values for X and Y. +// +// RP_SCREENMODE_SUBPIXEL combined with RP_SCREENMODE_STRETCH allows for maximum "stretch to fill" with no black areas. +// +// +// Typical scenarios: +// +// - Window mode without lTargetWidth and lTargetHeight set (user clicks 1X, 2X, etc. to resize) +// - Window mode with lTargetWidth and lTargetHeight set (user resizes via window resize corner) +// - Full-screen mode +// - Real-time clip changes (users clicks a control and uses cursor keys to visually adjust clip) +// +// +// Full-window Examples +// +// Example 1: No RP_SCREENMODE_SUBPIXEL, no RP_SCREENMODE_STRETCH: maximum integer scaling (can have black bars on up to four sides) +// +// Example 2: RP_SCREENMODE_SUBPIXEL, no RP_SCREENMODE_STRETCH: maximum "soft" scaling keeping ratio (can have black bars on two sides) +// +// Example 3: RP_SCREENMODE_SUBPIXEL combined with RP_SCREENMODE_STRETCH: maximum "stretch to fill" with no black areas +// +// There is a (theoretical) fourth case (RP_SCREENMODE_STRETCH without RP_SCREENMODE_SUBPIXEL), which could result in different integer multiplications along each axis. The player will not request such a mode. +// +// +// Clipping Examples +// +// In the following examples it is assumed that RP_SCREENMODE_SUBPIXEL and RP_SCREENMODE_STRETCH are cleared unless specified otherwise. +// +// Example 1: An Amiga game with known clip offset/size will have lClipLeft/Top/Width/Height set, and no RP_CLIPFLAGS. // In windowed mode, the guest (e.g. WinUAE) will take the net clipped region and apply RP_SCREENMODE_xX scaling to that. -// In RP_SCREENMODE_FULLWINDOW mode, the net clipped region will be "soft-scaled" to the maximum possible (not necessarily an integer scaling factor), centered and padded by a black border. +// In RP_SCREENMODE_FULLWINDOW mode, the net clipped region will be scaled to the maximum possible (not necessarily an integer scaling factor, if RP_SCREENMODE_SUBPIXEL and RP_SCREENMODE_STRETCH are set), centered and padded by black bars if necessary (unless RP_SCREENMODE_SUBPIXEL and RP_SCREENMODE_STRETCH are set). // In one of the RP_SCREENMODE_FULLSCREEN modes, the net clipped region will be centered in the smallest possible compatible hardware mode (in consideration of RP_SCREENMODE_USETVM) and padded by a black border. -// If an Amiga application sets a different Amiga chipset screen mode, the "container" window size will remain unchanged. +// If an Amiga application sets a different Amiga chipset screen mode, the "container" window size will remain unchanged (because it is still constrained by the clipping values). // If an Amiga application sets a different RTG screen mode, the "container" window size will reflect the new RTG size (instead of the Amiga clip size) and apply RP_SCREENMODE_xX. // -// An unknown Amiga application or one that has no known clip offset/size will start with RP_CLIPFLAGS_AUTOCLIP. +// Example 2: An unknown Amiga application or one that has no known clip offset/size will start with RP_CLIPFLAGS_AUTOCLIP. // The guest (e.g. WinUAE) will apply whatever logic it can to minimize the visible overscan region. // The guest will send to the host the actual RPScreenMode data with the offset/size details that were applied. // In windowed mode, RP_SCREENMODE_xX scaling is applied like in the previous example. // RP_SCREENMODE_FULLWINDOW and RP_SCREENMODE_FULLSCREEN modes behave like in the previous example (scaling, etc.) -// If an Amiga application sets a different Amiga or RTG chipset screen mode, the "container" window size may change. +// If an Amiga application sets a different Amiga or RTG chipset screen mode, the "container" window size may change (because it is not constrained by any host-set clipping values), in consideration of RP_SCREENMODE_xX. +// +// +// Notes +// +// If the user wants to adjust clipping, or for automated grabs and calculations, it is possible to set RP_CLIPFLAGS_NOCLIP, which will widen the window to the maximum (within lTargetWidth+lTargetHeight/full-screen constraints). +// +// Whenever the guest sets or changes the "container" window size or scaling factor (initially, or due to a command it receives, or due to Amiga-sourced changes), it sends an RPScreenMode update to the host. +// +// In window mode, if no lTargetWidth and lTargetHeight are set, when the host asks for a change in clipping (net content size), the host window size will be adjusted taking into account the current integer multiplication factor. // -// If the user wants to adjust clipping, or for automated grabs and calculations, it is possible to set RP_CLIPFLAGS_NOCLIP, which will widen the window to the maximum. +// In window mode, after a change of clipping or size, the player may have to reset the visual hilight of the 1X, 2X etc. buttons according to new RPIPCGM_SCREENMODE data (setting a hilight if the correct scaling button is present in the user interface, or removing all hilights if the corresponding button is missing). // -// Whenever the guest sets or changes the "container" window size (initially, or due to a command it receives, or due to Amiga-sourced changes), it sends a RPScreenMode update to the host. typedef struct RPScreenMode { DWORD dwScreenMode; // RP_SCREENMODE_* values and flags - LONG lClipLeft; // -1 = ignore (0 is a valid value) - LONG lClipTop; // -1 = ignore (0 is a valid value) - LONG lClipWidth; // -1 = ignore - LONG lClipHeight; // -1 = ignore + LONG lClipLeft; // in guest pixel units; -1 = ignore (0 is a valid value) + LONG lClipTop; // in guest pixel units; -1 = ignore (0 is a valid value) + LONG lClipWidth; // in guest pixel units; -1 = ignore + LONG lClipHeight; // in guest pixel units; -1 = ignore HWND hGuestWindow; // only valid for RPIPCGM_SCREENMODE - DWORD dwClipFlags; + DWORD dwClipFlags; // clip flags (or 0) + LONG lTargetWidth; // in exact host pixels; if set, must also set lTargetHeight; ignored unless RP_SCREENMODE_WW is set (resulting size is result of clipping and scaling); RP_SCREENMODE_SUBPIXEL and RP_SCREENMODE_STRETCH are taken into account + LONG lTargetHeight; // in exact host pixels, used with lTargetWidth } RPSCREENMODE; // Device Categories @@ -190,9 +245,10 @@ typedef struct RPDeviceContent #define RP_JOYSTICK_BUTTON2 0x00000020 // button 2 - Fire 2 - CD32 Blue #define RP_JOYSTICK_BUTTON3 0x00000040 // button 3 - Fire 3 - CD32 Yellow #define RP_JOYSTICK_BUTTON4 0x00000080 // button 4 - Fire 4 - CD32 Green -#define RP_JOYSTICK_BUTTON5 0x00000100 // button 5 - CD32 Play -#define RP_JOYSTICK_BUTTON6 0x00000200 // button 6 - CD32 Reverse -#define RP_JOYSTICK_BUTTON7 0x00000400 // button 7 - CD32 Forward +#define RP_JOYSTICK_BUTTON5 0x00000100 // button 5 - CDTV/CD32 Play/Pause +#define RP_JOYSTICK_BUTTON6 0x00000200 // button 6 - CDTV/CD32 Reverse +#define RP_JOYSTICK_BUTTON7 0x00000400 // button 7 - CDTV/CD32 Forward +// To clarify: Where is the CDTV Stop button? Does the CD32 joypad have Stop? // Device Read/Write status #define RP_DEVICE_READONLY 0 // the medium is write-protected diff --git a/od-win32/direct3d.cpp b/od-win32/direct3d.cpp index ddc6d027..1d498980 100644 --- a/od-win32/direct3d.cpp +++ b/od-win32/direct3d.cpp @@ -50,6 +50,7 @@ static IDirect3DDevice9 *d3ddev; static IDirect3DDevice9Ex *d3ddevex; static D3DSURFACE_DESC dsdbb; static LPDIRECT3DTEXTURE9 texture, sltexture, ledtexture, masktexture, mask2texture, blanktexture; +static IDirect3DQuery9 *query; static int masktexture_w, masktexture_h; static float mask2texture_w, mask2texture_h, mask2texture_ww, mask2texture_wh; static float mask2texture_multx, mask2texture_multy, mask2texture_offsetw; @@ -1657,6 +1658,10 @@ static void settransform (void) static void invalidatedeviceobjects (void) { + if (query) { + query->Release(); + query = NULL; + } if (texture) { texture->Release (); texture = NULL; @@ -1894,6 +1899,7 @@ const TCHAR *D3D_init (HWND ahwnd, int w_w, int w_h, int t_w, int t_h, int depth HINSTANCE d3dDLL, d3dx; typedef HRESULT (WINAPI *LPDIRECT3DCREATE9EX)(UINT, IDirect3D9Ex**); LPDIRECT3DCREATE9EX d3dexp = NULL; + bool newvsync = currprefs.gfx_avsync && currprefs.gfx_avsyncmode && !picasso_on; D3D_free2 (); if (!currprefs.gfx_api) { @@ -1966,12 +1972,12 @@ const TCHAR *D3D_init (HWND ahwnd, int w_w, int w_h, int t_w, int t_h, int depth memset (&dpp, 0, sizeof (dpp)); dpp.Windowed = isfullscreen () <= 0; dpp.BackBufferFormat = mode.Format; - dpp.BackBufferCount = dpp.Windowed || !currprefs.gfx_avsync ? 1 : currprefs.gfx_backbuffers; + dpp.BackBufferCount = newvsync ? 0 : (dpp.Windowed || !currprefs.gfx_avsync ? 1 : currprefs.gfx_backbuffers); dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; dpp.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER; dpp.BackBufferWidth = w_w; dpp.BackBufferHeight = w_h; - dpp.PresentationInterval = dpp.Windowed || currprefs.gfx_backbuffers == 0 ? D3DPRESENT_INTERVAL_IMMEDIATE : D3DPRESENT_INTERVAL_ONE; + dpp.PresentationInterval = dpp.Windowed || currprefs.gfx_backbuffers == 0 || newvsync ? D3DPRESENT_INTERVAL_IMMEDIATE : D3DPRESENT_INTERVAL_ONE; modeex.Width = w_w; modeex.Height = w_h; @@ -1980,7 +1986,7 @@ const TCHAR *D3D_init (HWND ahwnd, int w_w, int w_h, int t_w, int t_h, int depth modeex.Format = mode.Format; vsync2 = 0; - if (isfullscreen() > 0) { + if (isfullscreen () > 0) { dpp.FullScreen_RefreshRateInHz = currprefs.gfx_refreshrate > 0 ? currprefs.gfx_refreshrate : 0; modeex.RefreshRate = dpp.FullScreen_RefreshRateInHz; if (currprefs.gfx_avsync && currprefs.gfx_avsyncmode == 0) { @@ -2141,6 +2147,12 @@ const TCHAR *D3D_init (HWND ahwnd, int w_w, int w_h, int t_w, int t_h, int depth maxscanline = 0; d3d_enabled = 1; + if (newvsync) { + d3ddev->CreateQuery(D3DQUERYTYPE_EVENT, &query); + } + if (d3ddevex) + d3ddevex->SetMaximumFrameLatency (1); + return 0; } @@ -2211,7 +2223,7 @@ void D3D_clear (void) } } -static void D3D_render22 (void) +static void D3D_render2 (void) { HRESULT hr; LPDIRECT3DTEXTURE9 srctex = texture; @@ -2478,18 +2490,6 @@ static void D3D_render22 (void) hr = d3ddev->EndScene (); if (FAILED (hr)) write_log (L"%s: EndScene() %s\n", D3DHEAD, D3D_ErrorString (hr)); - hr = d3ddev->Present (NULL, NULL, NULL, NULL); - if (FAILED (hr)) { - write_log (L"%s: Present() %s\n", D3DHEAD, D3D_ErrorString (hr)); - if (hr == D3DERR_DEVICELOST) { - devicelost = 1; - } - } -} - -static void D3D_render2 (void) -{ - D3D_render22 (); } void D3D_setcursor (int x, int y, int visible) @@ -2562,17 +2562,42 @@ uae_u8 *D3D_locktexture (int *pitch, int fullupdate) return (uae_u8*)lock.pBits; } -void D3D_flip (void) +bool D3D_renderframe (void) { static int frameskip; + if (!isd3d ()) - return; + return false; if (currprefs.turbo_emulation && isfullscreen () > 0 && frameskip-- > 0) - return; + return false; frameskip = 50; + D3D_render2 (); - if (vsync2 && !currprefs.turbo_emulation) + if (vsync2 && !currprefs.turbo_emulation) { D3D_render2 (); + } + + if (query) { + if (SUCCEEDED (query->Issue (D3DISSUE_END))) { + while (query->GetData (NULL, 0, D3DGETDATA_FLUSH) == S_FALSE); + } + } + return true; +} + +void D3D_showframe (void) +{ + HRESULT hr; + + if (!isd3d ()) + return; + hr = d3ddev->Present (NULL, NULL, NULL, NULL); + if (FAILED (hr)) { + write_log (L"%s: Present() %s\n", D3DHEAD, D3D_ErrorString (hr)); + if (hr == D3DERR_DEVICELOST) { + devicelost = 1; + } + } } void D3D_refresh (void) @@ -2580,7 +2605,9 @@ void D3D_refresh (void) if (!isd3d ()) return; D3D_render2 (); + D3D_showframe (); D3D_render2 (); + D3D_showframe (); createscanlines (0); } diff --git a/od-win32/direct3d.h b/od-win32/direct3d.h index db0673cd..5139bd17 100644 --- a/od-win32/direct3d.h +++ b/od-win32/direct3d.h @@ -3,7 +3,8 @@ extern void D3D_free (void); extern const TCHAR *D3D_init (HWND ahwnd, int w_w, int w_h, int t_w, int t_h, int depth, int mult); extern void D3D_getpixelformat (int depth,int *rb, int *bb, int *gb, int *rs, int *bs, int *gs, int *ab, int *ar, int *a); extern void D3D_refresh (void); -extern void D3D_flip (void); +extern bool D3D_renderframe (void); +extern void D3D_showframe (void); extern uae_u8 *D3D_locktexture(int*,int); extern void D3D_unlocktexture(void); extern void D3D_flushtexture (int miny, int maxy); diff --git a/od-win32/rp.cpp b/od-win32/rp.cpp index 4c01ac49..831f3ec7 100644 --- a/od-win32/rp.cpp +++ b/od-win32/rp.cpp @@ -52,6 +52,7 @@ static int rp_filter, rp_filter_default; static int recursive_device, recursive; static int currentpausemode; static int gameportmask[MAX_JPORTS]; +static DWORD storeflags; static int cando (void) { @@ -409,8 +410,6 @@ static void get_screenmode (struct RPScreenMode *sm, struct uae_prefs *p) sm->lClipHeight = shift (p->gfx_size_win.height, -(VRES_MAX - vres)); } - if (full && p->gfx_filter && p->gfx_filter_horiz_zoom_mult == 0) - m = RP_SCREENMODE_XX; if (p->gfx_filter_scanlines || p->gfx_scanlines) m |= RP_SCREENMODE_SCANLINES; @@ -420,13 +419,20 @@ static void get_screenmode (struct RPScreenMode *sm, struct uae_prefs *p) cf |= RP_CLIPFLAGS_AUTOCLIP; } if (full) { - m &= ~0x0000ff00; + m &= ~RP_SCREENMODE_DISPLAYMASK; m |= p->gfx_display << 8; } if (full > 1) m |= RP_SCREENMODE_FULLWINDOW; - sm->dwScreenMode = m; + sm->dwScreenMode = m | (storeflags & (RP_SCREENMODE_STRETCH | RP_SCREENMODE_SUBPIXEL)); + if ((storeflags & RP_SCREENMODE_MODEMASK) == RP_SCREENMODE_XX) { + sm->dwScreenMode |= RP_SCREENMODE_XX; + } else if ((storeflags & RP_SCREENMODE_MODEMASK) == RP_SCREENMODE_WW) { + sm->dwScreenMode |= RP_SCREENMODE_WW; + sm->lTargetWidth = p->gfx_size_win.width; + sm->lTargetHeight = p->gfx_size_win.height; + } sm->dwClipFlags = cf; if (log_rp) @@ -444,7 +450,11 @@ static void set_screenmode (struct RPScreenMode *sm, struct uae_prefs *p) int hres, vres; int hmult = 1, vmult = 1; struct MultiDisplay *disp; + bool keepaspect = (sm->dwScreenMode & RP_SCREENMODE_SUBPIXEL) && !(sm->dwScreenMode & RP_SCREENMODE_STRETCH); + bool stretch = (sm->dwScreenMode & RP_SCREENMODE_STRETCH) != 0; + bool forcesize = smm == RP_SCREENMODE_WW && sm->lTargetWidth > 0 && sm->lTargetHeight > 0; + storeflags = sm->dwScreenMode; minimized = 0; if (display) { p->gfx_display = display; @@ -501,6 +511,11 @@ static void set_screenmode (struct RPScreenMode *sm, struct uae_prefs *p) p->gfx_size_win.height = sm->lClipHeight >> (VRES_MAX - vdbl); } + if (forcesize) { + p->gfx_size_win.width = sm->lTargetWidth; + p->gfx_size_win.height = sm->lTargetHeight; + } + if (fs == 1) { p->gfx_size_fs.width = p->gfx_size_win.width; p->gfx_size_fs.height = p->gfx_size_win.height; @@ -509,27 +524,22 @@ static void set_screenmode (struct RPScreenMode *sm, struct uae_prefs *p) p->gfx_size_fs.height = disp->rect.bottom - disp->rect.top; } - if (fs) { - if (smm == RP_SCREENMODE_XX) { - p->gfx_filter = rp_filter; - } else { - int mult; - int prevmult = 1; - int xmult = uaefilters[p->gfx_filter].intmul; - int ymult = uaefilters[p->gfx_filter].intmul ; - for (mult = 2; mult <= 4; mult += 2) { - int w = p->gfx_size_win.width; - int h = p->gfx_size_win.height; - if (p->gfx_size_fs.width * xmult < w * mult || p->gfx_size_fs.height * ymult < h * mult) { - mult = prevmult; - break; - } - prevmult = mult; - } - if (mult > 1 || fs == 2) { - p->gfx_filter = rp_filter; - hmult = vmult = mult; + if (smm == RP_SCREENMODE_XX) { + int mult; + int prevmult = 1; + int xmult = uaefilters[p->gfx_filter].intmul; + int ymult = uaefilters[p->gfx_filter].intmul; + for (mult = 2; mult <= 8; mult++) { + int w = p->gfx_size_win.width; + int h = p->gfx_size_win.height; + if (p->gfx_size_fs.width * xmult < w * mult || p->gfx_size_fs.height * ymult < h * mult) { + mult = prevmult; + break; } + prevmult = mult; + } + if (mult > 1) { + hmult = vmult = mult; } } @@ -537,16 +547,18 @@ static void set_screenmode (struct RPScreenMode *sm, struct uae_prefs *p) p->gfx_pfullscreen = fs; p->gfx_afullscreen = fs; p->win32_rtgscaleifsmall = fs == 2; -#if 1 - if (fs) { + if (stretch) { + hmult = vmult = 0; + } + if (keepaspect) { p->gfx_filter_aspect = -1; p->gfx_filter_keep_aspect = 1; } else { p->gfx_filter_aspect = 0; p->gfx_filter_keep_aspect = 0; } -#endif - write_log(L"%dx%d %dx%d %08x\n", sm->lClipLeft, sm->lClipTop, sm->lClipWidth, sm->lClipHeight, sm->dwClipFlags); + write_log(L"%dx%d %dx%d %dx%d %08x\n", + sm->lClipLeft, sm->lClipTop, sm->lClipWidth, sm->lClipHeight, sm->lTargetWidth, sm->lTargetHeight, sm->dwClipFlags); p->gfx_xcenter_pos = sm->lClipLeft; p->gfx_ycenter_pos = sm->lClipTop; @@ -556,7 +568,7 @@ static void set_screenmode (struct RPScreenMode *sm, struct uae_prefs *p) p->gfx_ycenter_size = sm->lClipHeight; if (sm->dwClipFlags & RP_CLIPFLAGS_AUTOCLIP) { - if (!fs) + if (!forcesize) p->gfx_filter_autoscale = AUTOSCALE_RESIZE; else p->gfx_filter_autoscale = AUTOSCALE_NORMAL; @@ -565,23 +577,23 @@ static void set_screenmode (struct RPScreenMode *sm, struct uae_prefs *p) p->gfx_xcenter_size = -1; p->gfx_ycenter_size = -1; } else if (sm->dwClipFlags & RP_CLIPFLAGS_NOCLIP) { - if (!fs) - p->gfx_filter_autoscale = AUTOSCALE_RESIZE; - else - p->gfx_filter_autoscale = AUTOSCALE_NORMAL; - p->gfx_xcenter_pos = 0; - p->gfx_ycenter_pos = 0; - p->gfx_xcenter_size = 1408; - p->gfx_ycenter_size = 568; + p->gfx_filter_autoscale = AUTOSCALE_STATIC_MAX; + p->gfx_xcenter_pos = -1; + p->gfx_ycenter_pos = -1; + p->gfx_xcenter_size = -1; + p->gfx_ycenter_size = -1; + if (!forcesize) { + p->gfx_size_win.width = AMIGA_WIDTH_MAX << currprefs.gfx_resolution; + p->gfx_size_win.height = AMIGA_HEIGHT_MAX << currprefs.gfx_vresolution;; + } } else if (p->gfx_xcenter_pos >= 0 || p->gfx_ycenter_pos >= 0) { p->gfx_filter_autoscale = AUTOSCALE_MANUAL; } else { p->gfx_filter_autoscale = AUTOSCALE_STATIC_NOMINAL; } - //p->gfx_filter = rp_filter_default; - p->gfx_filter_horiz_zoom_mult = 1000 / hmult; - p->gfx_filter_vert_zoom_mult = 1000 / vmult; + p->gfx_filter_horiz_zoom_mult = hmult ? 1000 / hmult : 0; + p->gfx_filter_vert_zoom_mult = vmult ? 1000 / vmult : 0; p->gfx_filter_scanlines = 0; p->gfx_scanlines = 0; @@ -593,13 +605,13 @@ static void set_screenmode (struct RPScreenMode *sm, struct uae_prefs *p) } if (log_rp) - write_log (L"WW=%d WH=%d FW=%d FH=%d HM=%d VM=%d XP=%d YP=%d XS=%d YS=%d AS=%d\n", + write_log (L"WW=%d WH=%d FW=%d FH=%d HM=%d VM=%d XP=%d YP=%d XS=%d YS=%d AS=%d AR=%d,%d\n", p->gfx_size_win.width, p->gfx_size_win.height, p->gfx_size_fs.width, p->gfx_size_fs.height, p->gfx_filter_horiz_zoom_mult, p->gfx_filter_vert_zoom_mult, p->gfx_xcenter_pos, p->gfx_ycenter_pos, p->gfx_xcenter_size, p->gfx_ycenter_size, - p->gfx_filter_autoscale); + p->gfx_filter_autoscale, p->gfx_filter_aspect, p->gfx_filter_keep_aspect); updatewinfsmode (p); @@ -855,6 +867,7 @@ static void sendfeatures (void) feat = RP_FEATURE_POWERLED | RP_FEATURE_SCREEN1X | RP_FEATURE_FULLSCREEN; feat |= RP_FEATURE_PAUSE | RP_FEATURE_TURBO | RP_FEATURE_VOLUME | RP_FEATURE_SCREENCAPTURE; feat |= RP_FEATURE_STATE | RP_FEATURE_SCANLINES | RP_FEATURE_DEVICEREADWRITE; + feat |= RP_FEATURE_RESIZE_SUBPIXEL | RP_FEATURE_RESIZE_STRETCH; if (!WIN32GFX_IsPicassoScreen ()) feat |= RP_FEATURE_SCREEN2X | RP_FEATURE_SCREEN4X; RPSendMessagex (RPIPCGM_FEATURES, feat, 0, NULL, 0, &guestinfo, NULL); diff --git a/od-win32/win32.h b/od-win32/win32.h index b2f94c76..3c397ab8 100644 --- a/od-win32/win32.h +++ b/od-win32/win32.h @@ -18,8 +18,8 @@ #define WINUAEPUBLICBETA 1 #define LANG_DLL 1 -#define WINUAEBETA L"Beta 2" -#define WINUAEDATE MAKEBD(2011, 7, 5) +#define WINUAEBETA L"Beta 3" +#define WINUAEDATE MAKEBD(2011, 7, 10) #define WINUAEEXTRA L"" #define WINUAEREV L"" diff --git a/od-win32/win32gfx.cpp b/od-win32/win32gfx.cpp index 86e1f9fa..c45b71c1 100644 --- a/od-win32/win32gfx.cpp +++ b/od-win32/win32gfx.cpp @@ -106,7 +106,7 @@ int window_extra_width, window_extra_height; static struct winuae_currentmode *currentmode = ¤tmodestruct; static int wasfullwindow_a, wasfullwindow_p; -static int vblankbase; +static int vblankbasewait, vblankbasefull; int screen_is_picasso = 0; @@ -831,17 +831,41 @@ void flush_screen (int a, int b) { } -void update_screen (void) +static bool render_ok; + +bool render_screen (void) { + bool v = false; + + render_ok = false; if (dx_islost ()) - return; + return render_ok; flushymin = 0; flushymax = currentmode->amiga_height; if (currentmode->flags & DM_D3D) { - D3D_flip (); + v = D3D_renderframe (); #ifdef GFXFILTER } else if (currentmode->flags & DM_SWSCALE) { S2X_render (); + v = true; +#endif + } else if (currentmode->flags & DM_DDRAW) { + v = true; + } + render_ok = v; + return render_ok; +} + +void show_screen (void) +{ + if (dx_islost ()) + return; + if (!render_ok) + return; + if (currentmode->flags & DM_D3D) { + D3D_showframe (); +#ifdef GFXFILTER + } else if (currentmode->flags & DM_SWSCALE) { DirectDraw_Flip (1); #endif } else if (currentmode->flags & DM_DDRAW) { @@ -1047,7 +1071,8 @@ void gfx_unlock_picasso (void) p96_double_buffer_needs_flushing = 0; } D3D_unlocktexture (); - D3D_flip (); + if (D3D_renderframe ()) + D3D_showframe (); } else { DirectDraw_SurfaceUnlock (); if (p96_double_buffer_needs_flushing) { @@ -2194,7 +2219,8 @@ double vblank_calibrate (double approx_vblank, bool waitonly) if (remembered_vblank > 0) return remembered_vblank; if (waitonly) { - vblankbase = (syncbase / approx_vblank) * 3 / 4; + vblankbasefull = syncbase / approx_vblank; + vblankbasewait = (syncbase / approx_vblank) * 3 / 4; remembered_vblank = -1; return -1; } @@ -2254,7 +2280,8 @@ double vblank_calibrate (double approx_vblank, bool waitonly) } if (tsum >= 85) tsum /= 2; - vblankbase = (syncbase / tsum) * 3 / 4; + vblankbasefull = (syncbase / tsum); + vblankbasewait = (syncbase / tsum) * 3 / 4; write_log (L"VSync calibration: %.6fHz\n", tsum); remembered_vblank = tsum; return tsum; @@ -2264,11 +2291,23 @@ bool vsync_busywait (void) { bool v; static frame_time_t prevtime; + static bool framelost; if (currprefs.turbo_emulation) return true; - while (read_processor_time () - prevtime < vblankbase) + if (!framelost && read_processor_time () - prevtime > vblankbasefull) { + framelost = true; + prevtime = read_processor_time (); + return true; + } + if (framelost) { + framelost = false; + prevtime = read_processor_time (); + return true; + } + + while (read_processor_time () - prevtime < vblankbasewait) sleep_millis (1); v = false; if (currprefs.gfx_api) { diff --git a/od-win32/win32gfx.h b/od-win32/win32gfx.h index d6107ce6..879ad095 100644 --- a/od-win32/win32gfx.h +++ b/od-win32/win32gfx.h @@ -33,7 +33,6 @@ extern void releasehdc (HDC hdc); extern void close_windows (void); extern void updatewinfsmode (struct uae_prefs *p); extern int is3dmode (void); -extern int vblankbase; void DX_Fill (int dstx, int dsty, int width, int height, uae_u32 color); void DX_Blit (int x, int y, int w, int h); diff --git a/od-win32/win32gui.cpp b/od-win32/win32gui.cpp index 457401da..f7fe7645 100644 --- a/od-win32/win32gui.cpp +++ b/od-win32/win32gui.cpp @@ -5797,13 +5797,26 @@ static void values_from_displaydlg (HWND hDlg, UINT msg, WPARAM wParam, LPARAM l TCHAR tmp[200]; workprefs.gfx_afullscreen = SendDlgItemMessage (hDlg, IDC_SCREENMODE_NATIVE, CB_GETCURSEL, 0, 0); + workprefs.gfx_lores_mode = ischecked (hDlg, IDC_LORES_SMOOTHED); + workprefs.gfx_scandoubler = ischecked (hDlg, IDC_FLICKERFIXER); + workprefs.gfx_blackerthanblack = ischecked (hDlg, IDC_BLACKER_THAN_BLACK); + workprefs.gfx_vresolution = (ischecked (hDlg, IDC_LM_DOUBLED) || ischecked (hDlg, IDC_LM_SCANLINES)) ? VRES_DOUBLE : VRES_NONDOUBLE; + workprefs.gfx_scanlines = ischecked (hDlg, IDC_LM_SCANLINES); + workprefs.gfx_backbuffers = SendDlgItemMessage (hDlg, IDC_DISPLAY_BUFFERCNT, CB_GETCURSEL, 0, 0); + workprefs.gfx_framerate = SendDlgItemMessage (hDlg, IDC_FRAMERATE, TBM_GETPOS, 0, 0); + i = SendDlgItemMessage (hDlg, IDC_SCREENMODE_NATIVE2, CB_GETCURSEL, 0, 0); + int oldmode = workprefs.gfx_avsyncmode; workprefs.gfx_avsync = 0; workprefs.gfx_avsyncmode = 0; if (i > 0) { i--; workprefs.gfx_avsync = (i & 1) + 1; workprefs.gfx_avsyncmode = i >= 2 ? 1 : 0; + if (workprefs.gfx_avsyncmode != oldmode && workprefs.gfx_avsyncmode) { + workprefs.gfx_backbuffers = 0; + SendDlgItemMessage (hDlg, IDC_DISPLAY_BUFFERCNT, CB_SETCURSEL, workprefs.gfx_backbuffers, 0); + } } workprefs.gfx_pfullscreen = SendDlgItemMessage (hDlg, IDC_SCREENMODE_RTG, CB_GETCURSEL, 0, 0); @@ -5816,14 +5829,6 @@ static void values_from_displaydlg (HWND hDlg, UINT msg, WPARAM wParam, LPARAM l workprefs.gfx_pvsyncmode = i >= 1 ? 1 : 0; } - workprefs.gfx_lores_mode = ischecked (hDlg, IDC_LORES_SMOOTHED); - workprefs.gfx_scandoubler = ischecked (hDlg, IDC_FLICKERFIXER); - workprefs.gfx_blackerthanblack = ischecked (hDlg, IDC_BLACKER_THAN_BLACK); - workprefs.gfx_vresolution = (ischecked (hDlg, IDC_LM_DOUBLED) || ischecked (hDlg, IDC_LM_SCANLINES)) ? VRES_DOUBLE : VRES_NONDOUBLE; - workprefs.gfx_scanlines = ischecked (hDlg, IDC_LM_SCANLINES); - workprefs.gfx_backbuffers = SendDlgItemMessage (hDlg, IDC_DISPLAY_BUFFERCNT, CB_GETCURSEL, 0, 0); - workprefs.gfx_framerate = SendDlgItemMessage (hDlg, IDC_FRAMERATE, TBM_GETPOS, 0, 0); - bool updaterate = false, updateslider = false; TCHAR label[16]; label[0] = 0; diff --git a/od-win32/winuaechangelog.txt b/od-win32/winuaechangelog.txt index 1d384907..5605e5d6 100644 --- a/od-win32/winuaechangelog.txt +++ b/od-win32/winuaechangelog.txt @@ -1,4 +1,9 @@ +Beta 3: + +- tearing in new vsync modes should be completely gone, without introducing any extra latency +- Display panel buffering option now does nothing in new vsync modes + Beta 2: - experimental joystick raw input support, enable using -rawhid command line parameter. -- 2.47.3