Skip to content
Browse files

MP1-4100 : Rework Refresh Changer by rework Win32 API on C# and Win7 …

…API on C++ side. It fix issue on multi screen setup and also GPU#1 / GPU#2.
  • Loading branch information...
1 parent 1f36763 commit 0776e7da6d298bd97531274214beab9fb01a29a7 @Sebastiii Sebastiii committed Aug 2, 2013
View
9 DirectShowFilters/DirectShowHelper/source/EVRCustomPresenter.cpp
@@ -60,7 +60,7 @@ void LogGUID(REFGUID guid)
CoTaskMemFree(str);
}
-MPEVRCustomPresenter::MPEVRCustomPresenter(IVMR9Callback* pCallback, IDirect3DDevice9* direct3dDevice, HMONITOR monitor, IBaseFilter** EVRFilter, BOOL pIsWin7):
+MPEVRCustomPresenter::MPEVRCustomPresenter(IVMR9Callback* pCallback, IDirect3DDevice9* direct3dDevice, HMONITOR monitor, IBaseFilter** EVRFilter, BOOL pIsWin7, int monitorIdx):
CUnknown(NAME("MPEVRCustomPresenter"), NULL),
m_refCount(1),
m_qScheduledSamples(MAX_SURFACES),
@@ -98,6 +98,7 @@ MPEVRCustomPresenter::MPEVRCustomPresenter(IVMR9Callback* pCallback, IDirect3DDe
Log("--- v1.6.%d Unicode with DWM queue support --- instance 0x%x", DSHOWHELPER_VERSION, this);
Log("---------- audio renderer enabled ------------- instance 0x%x", this);
}
+ m_monitorIdx = monitorIdx;
m_hMonitor = monitor;
m_pD3DDev = direct3dDevice;
hr = m_pDXVA2CreateDirect3DDeviceManager9(&m_iResetToken, &m_pDeviceManager);
@@ -3605,7 +3606,7 @@ BOOL MPEVRCustomPresenter::EstimateRefreshTimings(int numFrames, int threadPrior
dParams.dDetectedScanlineTime = scanLineTime / 10000.0;
m_pD3DDev->GetDisplayMode(0, &m_displayMode); //update this just in case anything has changed...
- GetRealRefreshRate(); // update m_dD3DRefreshCycle and m_dD3DRefreshRate values
+ GetRealRefreshRate(m_monitorIdx); // update m_dD3DRefreshCycle and m_dD3DRefreshRate values
if ((dParams.dEstRefreshCycle < 5.0) || (dParams.dEstRefreshCycle > 100.0)) // just in case it's gone badly wrong...
{
@@ -4263,12 +4264,12 @@ void MPEVRCustomPresenter::VideoFpsFromSample(IMFSample* pSample)
// get driver refresh rate
-void MPEVRCustomPresenter::GetRealRefreshRate()
+void MPEVRCustomPresenter::GetRealRefreshRate(int monitorIdx)
{
// Win7
if (m_bIsWin7 && m_pW7GetRefreshRate)
{
- m_dD3DRefreshRate = m_pW7GetRefreshRate();
+ m_dD3DRefreshRate = m_pW7GetRefreshRate(monitorIdx);
if (m_dD3DRefreshRate == -1)
{
View
5 DirectShowFilters/DirectShowHelper/source/EVRCustomPresenter.h
@@ -179,7 +179,7 @@ class MPEVRCustomPresenter :
{
public:
- MPEVRCustomPresenter(IVMR9Callback* pCallback, IDirect3DDevice9* direct3dDevice, HMONITOR monitor, IBaseFilter** EVRFilter, BOOL pIsWin7);
+ MPEVRCustomPresenter(IVMR9Callback* pCallback, IDirect3DDevice9* direct3dDevice, HMONITOR monitor, IBaseFilter** EVRFilter, BOOL pIsWin7, int MonnitorIdx);
virtual ~MPEVRCustomPresenter();
//IQualProp (stub)
@@ -344,7 +344,7 @@ friend class StatsRenderer;
void ReturnSample(IMFSample* pSample, BOOL tryNotify, BOOL isWorker);
HRESULT PresentSample(IMFSample* pSample);
void VideoFpsFromSample(IMFSample* pSample);
- void GetRealRefreshRate();
+ void GetRealRefreshRate(int monitorIdx);
LONGLONG GetDelayToRasterTarget(LONGLONG *targetTime, LONGLONG *offsetTime);
void DwmEnableMMCSSOnOff(bool enable);
bool BufferMoreSamples();
@@ -457,6 +457,7 @@ friend class StatsRenderer;
int m_regFPSLimV;
int m_regFPSLimH;
bool m_bOddFrame;
+ int m_monitorIdx;
int m_nNextSyncOffset;
LONGLONG nsSampleTime;
View
4 DirectShowFilters/DirectShowHelper/source/dshowhelper.cpp
@@ -630,7 +630,7 @@ HRESULT MyGetService(IUnknown* punkObject, REFGUID guidService, REFIID riid, LPV
}
-BOOL EvrInit(IVMR9Callback* callback, DWORD dwD3DDevice, IBaseFilter** evrFilter, DWORD monitor)
+BOOL EvrInit(IVMR9Callback* callback, DWORD dwD3DDevice, IBaseFilter** evrFilter, DWORD monitor, int monitorIdx)
{
HRESULT hr;
m_RenderPrefix = _T("evr");
@@ -651,7 +651,7 @@ BOOL EvrInit(IVMR9Callback* callback, DWORD dwD3DDevice, IBaseFilter** evrFilter
#ifndef DEFAULT_PRESENTER
- m_evrPresenter = new MPEVRCustomPresenter(callback, m_pDevice, (HMONITOR)monitor, evrFilter, IsWin7());
+ m_evrPresenter = new MPEVRCustomPresenter(callback, m_pDevice, (HMONITOR)monitor, evrFilter, IsWin7(), monitorIdx);
m_pVMR9Filter = (*evrFilter);
CComQIPtr<IMFVideoRenderer> pRenderer = m_pVMR9Filter;
View
2 DirectShowFilters/DirectShowHelper/source/dshowhelper.h
@@ -74,7 +74,7 @@ typedef HRESULT __stdcall TDwmGetCompositionTimingInfo(HWND hwnd, __out DWM_TIMI
extern TDwmGetCompositionTimingInfo* m_pDwmGetCompositionTimingInfo;
-typedef double __stdcall TW7GetRefreshRate();
+typedef double __cdecl TW7GetRefreshRate(int monitorIdx);
extern TW7GetRefreshRate* m_pW7GetRefreshRate;
typedef HANDLE __stdcall TAvSetMmThreadCharacteristicsW(LPCWSTR TaskName, LPDWORD TaskIndex);
View
70 DirectShowFilters/Win7RefreshRateHelper/source/Win7RefreshRateHelper.cpp
@@ -22,69 +22,83 @@
#include "Win7RefreshRateHelper.h"
// Get current refresh rate on Win7
-double W7GetRefreshRate()
+double W7GetRefreshRate(int monitorIdx)
{
- UINT32 uNumPathArrayElements = 0;
+ UINT32 uNumPathArrayElements = 0;
UINT32 uNumModeInfoArrayElements = 0;
DISPLAYCONFIG_PATH_INFO* pPathInfoArray = NULL;
DISPLAYCONFIG_MODE_INFO* pModeInfoArray = NULL;
DISPLAYCONFIG_TOPOLOGY_ID* pCurrentTopologyId = NULL;
LONG result;
double refreshRate = -1;
+ DISPLAY_DEVICE displayDevice;
+ displayDevice.cb = sizeof(DISPLAY_DEVICE);
+ DEVMODE devMode;
+ devMode.dmSize = sizeof(DEVMODE);
+ DEVMODE *paDeviceMode;
+
+ if(EnumDisplayDevices(NULL, monitorIdx, &displayDevice, 0))
+ {
+ EnumDisplaySettings(displayDevice.DeviceName, ENUM_CURRENT_SETTINGS, &devMode);
+ }
+ paDeviceMode = &devMode;
// Get size of buffers for QueryDisplayConfig
- result = GetDisplayConfigBufferSizes(QDC_ALL_PATHS, &uNumPathArrayElements, &uNumModeInfoArrayElements);
- if (result != 0)
- {
- return(refreshRate);
- }
+ result = GetDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &uNumPathArrayElements, &uNumModeInfoArrayElements);
+ if (result != 0)
+ {
+ return(refreshRate);
+ }
// allocate memory for QueryDisplayConfig buffers
pPathInfoArray = (DISPLAYCONFIG_PATH_INFO*)calloc(uNumPathArrayElements, sizeof(DISPLAYCONFIG_PATH_INFO));
if (pPathInfoArray == NULL)
- {
+ {
return(refreshRate);
}
pModeInfoArray = (DISPLAYCONFIG_MODE_INFO*)calloc(uNumModeInfoArrayElements, sizeof(DISPLAYCONFIG_MODE_INFO));
if (pModeInfoArray == NULL)
- {
+ {
// freeing memory
free(pPathInfoArray);
return(refreshRate);
}
// get display configuration
- result = QueryDisplayConfig(QDC_ALL_PATHS,
+ result = QueryDisplayConfig(QDC_ONLY_ACTIVE_PATHS,
&uNumPathArrayElements, pPathInfoArray,
&uNumModeInfoArrayElements, pModeInfoArray,
pCurrentTopologyId);
- if (result == 0)
- {
- // Get information from first active target path
- // TODO: add support for multiple displays (presenter doesn't know active display)
- for(int i=0; i < (int)uNumPathArrayElements; i++)
- {
- if (pPathInfoArray[i].flags == DISPLAYCONFIG_PATH_ACTIVE)
+ if (result == 0)
+ {
+ //// Get information from active target path and based on current dimension (support for multiple displays)
+ for (UINT i = 0; i < uNumPathArrayElements; ++i)
+ {
+ UINT iModIdx = pPathInfoArray[i].sourceInfo.modeInfoIdx;
+ if(pPathInfoArray[i].flags == DISPLAYCONFIG_PATH_ACTIVE && paDeviceMode[0].dmPosition.x == pModeInfoArray[iModIdx].sourceMode.position.x && paDeviceMode[0].dmPosition.y == pModeInfoArray[iModIdx].sourceMode.position.y)
{
- DISPLAYCONFIG_PATH_TARGET_INFO target;
- target = pPathInfoArray[i].targetInfo;
- LONG numerator = target.refreshRate.Numerator;
- LONG denominator = target.refreshRate.Denominator;
- refreshRate = (double)numerator/(double)denominator;
- break;
- }
+ if(paDeviceMode[0].dmPelsHeight == pModeInfoArray[iModIdx].sourceMode.height && paDeviceMode[0].dmPelsWidth == pModeInfoArray[iModIdx].sourceMode.width)
+ {
+ monitorIdx = i;
+ DISPLAYCONFIG_PATH_TARGET_INFO target;
+ target = pPathInfoArray[monitorIdx].targetInfo;
+ LONG numerator = target.refreshRate.Numerator;
+ LONG denominator = target.refreshRate.Denominator;
+ refreshRate = (double)numerator/(double)denominator;
+ break;
+ }
+ }
}
}
// freeing memory
free(pPathInfoArray);
free(pModeInfoArray);
-
+
return(refreshRate);
}
-
BOOL APIENTRY DllMain(HMODULE hModule, DWORD nReason, LPVOID lpReserved)
{
- return TRUE;
-}
+ return TRUE;
+}
View
110 mediaportal/Core/Player/RefreshRateChanger.cs
@@ -189,48 +189,99 @@ public static extern ChangeDisplaySettings_Result
public static extern int DwmIsCompositionEnabled(ref int pfEnabled);
+ /// <summary>
+ /// Finds the monitorIndex based on current specified screen on its primary monitor
+ /// </summary>
+ /// <returns>The monitorIndex that has the specified screen on its primary monitor</returns>
+ protected static int FindMonitorIndexForScreen()
+ {
+ uint deviceNum = 0;
+ DISPLAY_DEVICE displayDevice = new DISPLAY_DEVICE();
+ displayDevice.cb = (ushort)Marshal.SizeOf(displayDevice);
+ while (EnumDisplayDevices(null, deviceNum, displayDevice, 0) != 0)
+ {
+ if (displayDevice.DeviceName == GUIGraphicsContext.currentScreen.DeviceName)
+ {
+ // Set new monitorIndex
+ GUIGraphicsContext.currentMonitorIdx = (int)deviceNum;
+ Log.Debug("CycleRefreshRate: return new detected MonitorIndex : {0}", (int)deviceNum);
+ return (int)deviceNum;
+ }
+ ++deviceNum;
+ }
+ Log.Debug("CycleRefreshRate: return current default MonitorIndex, detection failed to find the new one : {0}",
+ GUIGraphicsContext.DX9Device.DeviceCaps.AdapterOrdinal);
+ return GUIGraphicsContext.DX9Device.DeviceCaps.AdapterOrdinal;
+ }
+
public static void Win32_SetRefreshRate(uint monitorIndex, uint refreshRate)
{
- Win32.DISPLAY_DEVICE displayDevice = new Win32.DISPLAY_DEVICE();
- int result = Win32.EnumDisplayDevices(null, monitorIndex, displayDevice, 0);
+ DISPLAY_DEVICE displayDevice = new DISPLAY_DEVICE();
+ displayDevice.cb = (ushort)Marshal.SizeOf(displayDevice);
+ DEVMODE_Display devMode = new DEVMODE_Display();
+ devMode.dmSize = (ushort)Marshal.SizeOf(devMode);
+ int result = EnumDisplayDevices(null, monitorIndex, displayDevice, 0);
if (result != 0)
{
- Win32.DEVMODE_Display devMode = new Win32.DEVMODE_Display();
- devMode.dmFields = Win32.DEVMODE_Fields.DM_DISPLAYFREQUENCY;
- devMode.dmDisplayFrequency = refreshRate;
- Win32.ChangeDisplaySettings_Result r = Win32.ChangeDisplaySettingsEx(displayDevice.DeviceName, devMode,
- IntPtr.Zero,
- Win32.ChangeDisplaySettings_Flags.None,
- IntPtr.Zero);
- Log.Info("CycleRefreshRate: result {0} for refresh rate change {1}Hz", r, refreshRate);
- FixDwm();
+ Log.Debug("CycleRefreshRate: Current MonitorIndex : {0} and current deviceName : {1}", (int) monitorIndex,
+ GUIGraphicsContext.currentScreen.DeviceName);
+ if (displayDevice.DeviceName != GUIGraphicsContext.currentScreen.DeviceName)
+ {
+ // Analyse monitorIndex to be sure to get on the good one (some multiscreen setup can failed otherwise)
+ monitorIndex = (uint) FindMonitorIndexForScreen();
+
+ // Try to get new displayDevice based on newest detected monitorIndex
+ result = EnumDisplayDevices(null, monitorIndex, displayDevice, 0);
+ Log.Debug("CycleRefreshRate: New MonitorIndex : {0} based on current deviceName : {1}", (int) monitorIndex,
+ GUIGraphicsContext.currentScreen.DeviceName);
+ }
+
+ if (result != 0)
+ {
+ result = EnumDisplaySettingsEx(displayDevice.DeviceName, 0, devMode, 2);
+ if (result != 0)
+ {
+ result = EnumDisplaySettingsEx(displayDevice.DeviceName, EnumDisplaySettings_EnumMode.ENUM_CURRENT_SETTINGS, devMode, 2); // EDS_RAWMODE = 2
+
+ if (result != 0)
+ {
+ // Get current Value
+ uint Width = devMode.dmPelsWidth;
+ uint Height = devMode.dmPelsHeight;
+
+ //Log.Info("CycleRefreshRate: code result {0} enum devMode", result);
+ devMode.dmFields = (DEVMODE_Fields.DM_BITSPERPEL | DEVMODE_Fields.DM_PELSWIDTH |
+ DEVMODE_Fields.DM_PELSHEIGHT | DEVMODE_Fields.DM_DISPLAYFREQUENCY);
+ devMode.dmBitsPerPel = 32;
+ devMode.dmPelsWidth = Width;
+ devMode.dmPelsHeight = Height;
+ devMode.dmDisplayFrequency = refreshRate;
+
+ // First set settings
+ ChangeDisplaySettings_Result r = ChangeDisplaySettingsEx(displayDevice.DeviceName, devMode,
+ IntPtr.Zero,
+ (ChangeDisplaySettings_Flags
+ .CDS_NORESET |
+ ChangeDisplaySettings_Flags
+ .CDS_UPDATEREGISTRY),
+ IntPtr.Zero);
+ // Apply settings
+ r = ChangeDisplaySettingsEx(null, null, IntPtr.Zero, 0, IntPtr.Zero);
+ Log.Info("CycleRefreshRate: result {0} for refresh rate change {1}Hz", r, refreshRate);
+ FixDwm();
+ }
+ }
+ }
}
else
{
Log.Info("CycleRefreshRate: unable to change refresh rate {0}Hz for monitor {1}", refreshRate, monitorIndex);
}
}
-
public static void CycleRefreshRate(uint monitorIndex, double refreshRate)
{
- if (OSInfo.OSInfo.Win7OrLater())
- {
- if (W7RefreshRateHelper.SetRefreshRate(monitorIndex, refreshRate))
- {
- double newRefreshRate = W7RefreshRateHelper.GetRefreshRate(monitorIndex);
- Log.Info("CycleRefreshRate: successfully changed refresh rate to {0}Hz ({1}Hz requested)",
- newRefreshRate.ToString("#.###"), refreshRate);
- FixDwm();
- }
- else
- {
- Log.Info("CycleRefreshRate: unable to change refresh rate to {0}Hz for monitor {1}", refreshRate,
- monitorIndex);
- }
- }
- else
{
Win32_SetRefreshRate(monitorIndex, (uint)refreshRate);
}
@@ -675,6 +726,7 @@ public static void SetRefreshRateBasedOnFPS(double fps, string strFile, MediaTyp
if (newExtCmd.Length == 0)
{
Log.Info("RefreshRateChanger.SetRefreshRateBasedOnFPS: using internal win32 method for changing refreshrate. current is {0}hz, desired is {1}", currentRR, newRR);
+ Log.Info("RefreshRateChanger AdapterOrdinal value is {0}", (uint)GUIGraphicsContext.DX9Device.DeviceCaps.AdapterOrdinal);
Win32.CycleRefreshRate((uint)GUIGraphicsContext.DX9Device.DeviceCaps.AdapterOrdinal, newRR);
NotifyRefreshRateChanged(newRRDescription, (strFile.Length > 0));
}
@@ -684,7 +736,7 @@ public static void SetRefreshRateBasedOnFPS(double fps, string strFile, MediaTyp
NotifyRefreshRateChanged(newRRDescription, (strFile.Length > 0));
}
- if (GUIGraphicsContext.Vmr9Active)
+ if (GUIGraphicsContext.Vmr9Active && GUIGraphicsContext.IsEvr)
{
Log.Info("RefreshRateChanger.SetRefreshRateBasedOnFPS: dynamic refresh rate change - notify video renderer");
VMR9Util.g_vmr9.UpdateEVRDisplayFPS();
View
13 mediaportal/Core/Player/VMR9.cs
@@ -86,7 +86,7 @@ public class VMR9Util : IDisposable
[DllImport("dshowhelper.dll", ExactSpelling = true, CharSet = CharSet.Auto, SetLastError = true)]
private static extern unsafe bool EvrInit(IVMR9PresentCallback callback, uint dwD3DDevice,
- ref IBaseFilter vmr9Filter, uint monitor);
+ ref IBaseFilter vmr9Filter, uint monitor, int monitorIdx);
//, uint dwWindow);
[DllImport("dshowhelper.dll", ExactSpelling = true, CharSet = CharSet.Auto, SetLastError = true)]
@@ -375,8 +375,15 @@ public bool AddVMR9(IGraphBuilder graphBuilder)
_scene.Init();
if (_useEvr)
- {
- EvrInit(_scene, (uint)upDevice.ToInt32(), ref _vmr9Filter, (uint)hMonitor.ToInt32());
+ {
+ if (GUIGraphicsContext.currentMonitorIdx != -1)
+ {
+ EvrInit(_scene, (uint) upDevice.ToInt32(), ref _vmr9Filter, (uint) hMonitor.ToInt32(), GUIGraphicsContext.currentMonitorIdx);
+ }
+ else
+ {
+ EvrInit(_scene, (uint)upDevice.ToInt32(), ref _vmr9Filter, (uint)hMonitor.ToInt32(), GUIGraphicsContext.DX9Device.DeviceCaps.AdapterOrdinal);
+ }
hr = new HResult(graphBuilder.AddFilter(_vmr9Filter, "Enhanced Video Renderer"));
Log.Info("VMR9: added EVR Renderer to graph");
}
View
15 mediaportal/Core/guilib/GraphicContext.cs
@@ -130,6 +130,7 @@ public enum State
private static bool _vmr9Allowed = true;
private static DateTime _lastActivity = DateTime.Now;
private static Screen _currentScreen;
+ private static int _currentMonitorIdx = -1;
private static readonly bool IsDX9EXused = OSInfo.OSInfo.VistaOrLater();
private static bool _allowRememberLastFocusedItem = true;
@@ -283,6 +284,20 @@ public static Screen currentScreen
}
/// <summary>
+ /// Property to get and set current monitor index for refreshrate setting
+ /// </summary>
+ // ReSharper disable InconsistentNaming
+ public static int currentMonitorIdx
+ // ReSharper restore InconsistentNaming
+ {
+ get
+ {
+ return _currentMonitorIdx;
+ }
+ set { _currentMonitorIdx = value; }
+ }
+
+ /// <summary>
/// Property to get windowed/fullscreen state of application
/// </summary>
public static bool Fullscreen
View
6 mediaportal/MediaPortal.Application/MediaPortal.cs
@@ -1286,7 +1286,7 @@ private void RenderStats()
{
UpdateStats();
- if (GUIGraphicsContext.IsEvr && g_Player.HasVideo)
+ if (GUIGraphicsContext.IsEvr && g_Player.HasVideo && GUIGraphicsContext.Vmr9Active)
{
if (_showStats != _showStatsPrevious)
{
@@ -1797,6 +1797,10 @@ private void OnDeviceChange(ref Message msg)
private void OnDisplayChange(ref Message msg)
{
Log.Debug("Main: WM_DISPLAYCHANGE");
+ if (VMR9Util.g_vmr9 != null && GUIGraphicsContext.Vmr9Active && GUIGraphicsContext.IsEvr)
+ {
+ VMR9Util.g_vmr9.UpdateEVRDisplayFPS(); // Update FPS
+ }
Screen screen = Screen.FromControl(this);
if (Created && !Equals(screen, GUIGraphicsContext.currentScreen))
{

0 comments on commit 0776e7d

Please sign in to comment.
Something went wrong with that request. Please try again.