From e795de6bae9a84563111dc42e15041b65814b31b Mon Sep 17 00:00:00 2001 From: Anton Fedchin Date: Wed, 18 Nov 2015 15:19:32 +0300 Subject: [PATCH] [win32] Add handling of DispResResource. --- project/VS2010Express/XBMC.vcxproj | 1 + project/VS2010Express/XBMC.vcxproj.filters | 3 ++ .../VideoRenderers/WinRenderer.cpp | 9 ++-- xbmc/rendering/dx/RenderSystemDX.cpp | 22 +++++----- xbmc/rendering/dx/RenderSystemDX.h | 43 +++--------------- xbmc/windowing/windows/WinSystemWin32.cpp | 44 +++++++++++++++++++ xbmc/windowing/windows/WinSystemWin32.h | 13 ++++++ xbmc/windowing/windows/WinSystemWin32DX.cpp | 37 +++++++++++++++- xbmc/windowing/windows/WinSystemWin32DX.h | 21 +++++++++ 9 files changed, 136 insertions(+), 57 deletions(-) diff --git a/project/VS2010Express/XBMC.vcxproj b/project/VS2010Express/XBMC.vcxproj index 00a72e15d9bf1..56b4e0d8edd3e 100644 --- a/project/VS2010Express/XBMC.vcxproj +++ b/project/VS2010Express/XBMC.vcxproj @@ -976,6 +976,7 @@ + diff --git a/project/VS2010Express/XBMC.vcxproj.filters b/project/VS2010Express/XBMC.vcxproj.filters index 9e4a08a700c69..686c7076bb34e 100644 --- a/project/VS2010Express/XBMC.vcxproj.filters +++ b/project/VS2010Express/XBMC.vcxproj.filters @@ -6262,6 +6262,9 @@ pvr + + guilib + diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/WinRenderer.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/WinRenderer.cpp index 3b14d13f4aea1..1738808a6b5b9 100644 --- a/xbmc/cores/VideoPlayer/VideoRenderers/WinRenderer.cpp +++ b/xbmc/cores/VideoPlayer/VideoRenderers/WinRenderer.cpp @@ -239,9 +239,9 @@ bool CWinRenderer::Configure(unsigned int width, unsigned int height, unsigned i // calculate the input frame aspect ratio CalculateFrameAspectRatio(d_width, d_height); - ChooseBestResolution(fps); - m_destWidth = g_graphicsContext.GetResInfo(m_resolution).iWidth; - m_destHeight = g_graphicsContext.GetResInfo(m_resolution).iHeight; + RESOLUTION_INFO res = g_graphicsContext.GetResInfo(g_graphicsContext.GetVideoResolution()); + m_destWidth = res.iWidth; + m_destHeight = res.iHeight; SetViewMode(CMediaSettings::GetInstance().GetCurrentVideoSettings().m_ViewMode); ManageDisplay(); @@ -402,9 +402,6 @@ void CWinRenderer::PreInit() CSingleLock lock(g_graphicsContext); m_bConfigured = false; UnInit(); - m_resolution = CDisplaySettings::GetInstance().GetCurrentResolution(); - if ( m_resolution == RES_WINDOW ) - m_resolution = RES_DESKTOP; // setup the background colour m_clearColour = g_Windowing.UseLimitedColor() ? (16 * 0x010101) : 0; diff --git a/xbmc/rendering/dx/RenderSystemDX.cpp b/xbmc/rendering/dx/RenderSystemDX.cpp index 534fc7c20d247..5073fee80a082 100644 --- a/xbmc/rendering/dx/RenderSystemDX.cpp +++ b/xbmc/rendering/dx/RenderSystemDX.cpp @@ -389,7 +389,11 @@ void CRenderSystemDX::SetFullScreenInternal() // resize window (in windowed mode) or monitor resolution (in fullscreen mode) to required mode hr = m_pSwapChain->ResizeTarget(&matchedMode); - m_bResizeRequred = S_OK == hr; + if (S_OK == hr && !m_bResizeRequred) + { + m_bResizeRequred = true; + ResolutionChanged(); + } if (FAILED(hr)) CLog::Log(LOGERROR, "%s - Failed to switch output mode: %s", __FUNCTION__, GetErrorDescription(hr).c_str()); @@ -830,6 +834,10 @@ bool CRenderSystemDX::CreateWindowSizeDependentResources() Sleep(100); } + + // when transition from/to stereo mode trigger display reset event + if (bNeedRecreate) + ResolutionChanged(); } else { @@ -1099,7 +1107,7 @@ bool CRenderSystemDX::PresentRenderImpl(const CDirtyRegionList &dirty) { HRESULT hr; - if (!m_bRenderCreated) + if (!m_bRenderCreated || m_resizeInProgress) return false; if (m_nDeviceStatus != S_OK) @@ -1299,16 +1307,6 @@ bool CRenderSystemDX::IsExtSupported(const char* extension) return false; } -bool CRenderSystemDX::PresentRender(const CDirtyRegionList &dirty) -{ - if (!m_bRenderCreated || m_resizeInProgress) - return false; - - bool result = PresentRenderImpl(dirty); - - return result; -} - void CRenderSystemDX::SetVSync(bool enable) { m_bVSync = enable; diff --git a/xbmc/rendering/dx/RenderSystemDX.h b/xbmc/rendering/dx/RenderSystemDX.h index 44f4dddb6fbac..3e735f22a47aa 100644 --- a/xbmc/rendering/dx/RenderSystemDX.h +++ b/xbmc/rendering/dx/RenderSystemDX.h @@ -49,41 +49,31 @@ class CRenderSystemDX : public CRenderSystemBase virtual bool InitRenderSystem(); virtual bool DestroyRenderSystem(); virtual bool ResetRenderSystem(int width, int height, bool fullScreen, float refreshRate); - virtual bool BeginRender(); virtual bool EndRender(); - virtual bool PresentRender(const CDirtyRegionList &dirty); virtual bool ClearBuffers(color_t color); virtual bool IsExtSupported(const char* extension); virtual bool IsFormatSupport(DXGI_FORMAT format, unsigned int usage); - virtual void SetVSync(bool vsync); - virtual void SetViewPort(CRect& viewPort); virtual void GetViewPort(CRect& viewPort); virtual void RestoreViewPort(); - virtual CRect ClipRectToScissorRect(const CRect &rect); virtual bool ScissorsCanEffectClipping(); virtual void SetScissors(const CRect &rect); virtual void ResetScissors(); - virtual void CaptureStateBlock(); virtual void ApplyStateBlock(); - virtual void SetCameraPosition(const CPoint &camera, int screenWidth, int screenHeight, float stereoFactor = 0.f); - virtual void ApplyHardwareTransform(const TransformMatrix &matrix); virtual void RestoreHardwareTransform(); virtual void SetStereoMode(RENDER_STEREO_MODE mode, RENDER_STEREO_VIEW view); virtual bool SupportsStereo(RENDER_STEREO_MODE mode) const; virtual bool TestRender(); - - void GetDisplayMode(DXGI_MODE_DESC *mode, bool useCached = false); - IDXGIOutput* GetCurrentOutput(void) { return m_pOutput; } - virtual void Project(float &x, float &y, float &z); + IDXGIOutput* GetCurrentOutput(void) { return m_pOutput; } + void GetDisplayMode(DXGI_MODE_DESC *mode, bool useCached = false); void FinishCommandList(bool bExecute = true); void FlushGPU(); @@ -98,24 +88,6 @@ class CRenderSystemDX : public CRenderSystemBase int GetBackbufferCount() const { return 2; } void SetAlphaBlendEnable(bool enable); - /*! - \brief Register as a dependent of the DirectX Render System - Resources should call this on construction if they're dependent on the Render System - for survival. Any resources that registers will get callbacks on loss and reset of - device, where resources that are in the D3DPOOL_DEFAULT pool should be handled. - In addition, callbacks for destruction and creation of the device are also called, - where any resources dependent on the DirectX device should be destroyed and recreated. - \sa Unregister, ID3DResource - */ - void Register(ID3DResource *resource); - - /*! - \brief Unregister as a dependent of the DirectX Render System - Resources should call this on destruction if they're a dependent on the Render System - \sa Register, ID3DResource - */ - void Unregister(ID3DResource *resource); - static std::string GetErrorDescription(HRESULT hr); protected: @@ -137,7 +109,10 @@ class CRenderSystemDX : public CRenderSystemBase void SetFullScreenInternal(); void GetClosestDisplayModeToCurrent(IDXGIOutput* output, DXGI_MODE_DESC* outCurrentDisplayMode, bool useCached = false); void CheckInterlasedStereoView(void); + void Register(ID3DResource *resource); + void Unregister(ID3DResource *resource); + virtual void ResolutionChanged() {}; virtual void UpdateMonitor() {}; // our adapter could change as we go @@ -145,7 +120,6 @@ class CRenderSystemDX : public CRenderSystemBase bool m_needNewViews; bool m_resizeInProgress; unsigned int m_screenHeight; - HWND m_hFocusWnd; HWND m_hDeviceWnd; unsigned int m_nBackBufferWidth; @@ -157,12 +131,9 @@ class CRenderSystemDX : public CRenderSystemBase int64_t m_systemFreq; D3D11_USAGE m_defaultD3DUsage; bool m_useWindowedDX; - CCriticalSection m_resourceSection; std::vector m_resources; - bool m_inScene; ///< True if we're in a BeginScene()/EndScene() block - D3D_DRIVER_TYPE m_driverType; D3D_FEATURE_LEVEL m_featureLevel; IDXGIFactory1* m_dxgiFactory; @@ -172,7 +143,6 @@ class CRenderSystemDX : public CRenderSystemBase IDXGIOutput* m_pOutput; ID3D11DeviceContext* m_pContext; ID3D11DeviceContext* m_pImdContext; - IDXGISwapChain* m_pSwapChain; IDXGISwapChain1* m_pSwapChain1; ID3D11RenderTargetView* m_pRenderTargetView; @@ -180,7 +150,6 @@ class CRenderSystemDX : public CRenderSystemBase ID3D11DepthStencilView* m_depthStencilView; D3D11_VIEWPORT m_viewPort; CRect m_scissor; - CGUIShaderDX* m_pGUIShader; ID3D11BlendState* m_BlendEnableState; ID3D11BlendState* m_BlendDisableState; @@ -189,14 +158,12 @@ class CRenderSystemDX : public CRenderSystemBase ID3D11RasterizerState* m_RSScissorEnable; bool m_ScissorsEnabled; DXGI_ADAPTER_DESC m_adapterDesc; - // stereo interlaced/checkerboard intermediate target ID3D11Texture2D* m_pTextureRight; ID3D11RenderTargetView* m_pRenderTargetViewRight; ID3D11ShaderResourceView* m_pShaderResourceViewRight; bool m_bResizeRequred; bool m_bHWStereoEnabled; - // improve get current mode DXGI_MODE_DESC m_cachedMode; #ifdef _DEBUG diff --git a/xbmc/windowing/windows/WinSystemWin32.cpp b/xbmc/windowing/windows/WinSystemWin32.cpp index 1aa15bc19dee7..cc8b8645915cd 100644 --- a/xbmc/windowing/windows/WinSystemWin32.cpp +++ b/xbmc/windowing/windows/WinSystemWin32.cpp @@ -22,9 +22,11 @@ #include "WinEventsWin32.h" #include "resource.h" #include "guilib/gui3d.h" +#include "messaging/ApplicationMessenger.h" #include "settings/AdvancedSettings.h" #include "settings/DisplaySettings.h" #include "settings/Settings.h" +#include "threads/SingleLock.h" #include "utils/log.h" #include "utils/CharsetConverter.h" #include "utils/SystemInfo.h" @@ -542,6 +544,9 @@ bool CWinSystemWin32::ChangeResolution(RESOLUTION_INFO res, bool forceChange /*= else CLog::Log(LOGERROR, "%s : ChangeDisplaySettingsEx failed with %d", __FUNCTION__, rc); } + + if (bResChanged) + ResolutionChanged(); return bResChanged; } @@ -782,4 +787,43 @@ bool CWinSystemWin32::Show(bool raise) return true; } +void CWinSystemWin32::Register(IDispResource *resource) +{ + CSingleLock lock(m_resourceSection); + m_resources.push_back(resource); +} + +void CWinSystemWin32::Unregister(IDispResource* resource) +{ + CSingleLock lock(m_resourceSection); + std::vector::iterator i = find(m_resources.begin(), m_resources.end(), resource); + if (i != m_resources.end()) + m_resources.erase(i); +} + +void CWinSystemWin32::OnDisplayLost() +{ + CLog::Log(LOGDEBUG, "%s - notify display change event", __FUNCTION__); + + // make sure renderer has no invalid references + KODI::MESSAGING::CApplicationMessenger::GetInstance().SendMsg(TMSG_RENDERER_FLUSH); + + { + CSingleLock lock(m_resourceSection); + for (std::vector::iterator i = m_resources.begin(); i != m_resources.end(); ++i) + (*i)->OnLostDisplay(); + } +} + +void CWinSystemWin32::ResolutionChanged() +{ + OnDisplayLost(); + int delay = CSettings::GetInstance().GetInt("videoscreen.delayrefreshchange"); + if (delay > 0) + { + m_delayDispReset = true; + m_dispResetTimer.Set(delay * 100); + } +} + #endif diff --git a/xbmc/windowing/windows/WinSystemWin32.h b/xbmc/windowing/windows/WinSystemWin32.h index 04404db9567f4..f6a85911a00b8 100644 --- a/xbmc/windowing/windows/WinSystemWin32.h +++ b/xbmc/windowing/windows/WinSystemWin32.h @@ -21,6 +21,9 @@ #ifndef WINDOW_SYSTEM_WIN32_H #define WINDOW_SYSTEM_WIN32_H +#include "guilib/DispResource.h" +#include "threads/CriticalSection.h" +#include "threads/SystemClock.h" #include "windowing/WinSystem.h" #include @@ -177,6 +180,11 @@ class CWinSystemWin32 : public CWinSystemBase */ void AddResolution(const RESOLUTION_INFO &res); + virtual void Register(IDispResource *resource); + virtual void Unregister(IDispResource *resource); + void OnDisplayLost(); + virtual void ResolutionChanged(); + HWND m_hWnd; std::vector m_hBlankWindows; HDC m_hDC; @@ -186,6 +194,11 @@ class CWinSystemWin32 : public CWinSystemBase int m_nPrimary; bool m_ValidWindowedPosition; bool m_IsAlteringWindow; + + CCriticalSection m_resourceSection; + std::vector m_resources; + bool m_delayDispReset; + XbmcThreads::EndTime m_dispResetTimer; }; extern HWND g_hWnd; diff --git a/xbmc/windowing/windows/WinSystemWin32DX.cpp b/xbmc/windowing/windows/WinSystemWin32DX.cpp index c2692275c8246..296c7d2dc4f8e 100644 --- a/xbmc/windowing/windows/WinSystemWin32DX.cpp +++ b/xbmc/windowing/windows/WinSystemWin32DX.cpp @@ -20,8 +20,9 @@ #include "WinSystemWin32DX.h" -#include "settings/Settings.h" #include "guilib/gui3d.h" +#include "settings/Settings.h" +#include "threads/SingleLock.h" #include "utils/CharsetConverter.h" #ifdef HAS_DX @@ -37,6 +38,20 @@ CWinSystemWin32DX::~CWinSystemWin32DX() } +bool CWinSystemWin32DX::PresentRender(const CDirtyRegionList& dirty) +{ + bool result = PresentRenderImpl(dirty); + if (m_delayDispReset && m_dispResetTimer.IsTimePast()) + { + m_delayDispReset = false; + CSingleLock lock(CWinSystemWin32::m_resourceSection); + // tell any shared resources + for (auto i = CWinSystemWin32::m_resources.begin(); i != CWinSystemWin32::m_resources.end(); ++i) + (*i)->OnResetDisplay(); + } + return result; +} + bool CWinSystemWin32DX::UseWindowedDX(bool fullScreen) { return (CSettings::GetInstance().GetBool(CSettings::SETTING_VIDEOSCREEN_FAKEFULLSCREEN) || !fullScreen); @@ -176,4 +191,24 @@ void CWinSystemWin32DX::NotifyAppFocusChange(bool bGaining) } } +void CWinSystemWin32DX::Register(ID3DResource *resource) +{ + CRenderSystemDX::Register(resource); +} + +void CWinSystemWin32DX::Unregister(ID3DResource *resource) +{ + CRenderSystemDX::Unregister(resource); +} + +void CWinSystemWin32DX::Register(IDispResource *resource) +{ + CWinSystemWin32::Register(resource); +} + +void CWinSystemWin32DX::Unregister(IDispResource *resource) +{ + CWinSystemWin32::Unregister(resource); +} + #endif diff --git a/xbmc/windowing/windows/WinSystemWin32DX.h b/xbmc/windowing/windows/WinSystemWin32DX.h index 06024eb5eda66..d338b22cec0e5 100644 --- a/xbmc/windowing/windows/WinSystemWin32DX.h +++ b/xbmc/windowing/windows/WinSystemWin32DX.h @@ -42,9 +42,30 @@ class CWinSystemWin32DX : public CWinSystemWin32, public CRenderSystemDX virtual bool SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool blankOtherDisplays); virtual bool WindowedMode() { return CRenderSystemDX::m_useWindowedDX; } virtual void NotifyAppFocusChange(bool bGaining); + virtual bool PresentRender(const CDirtyRegionList &dirty); std::string GetClipboardText(void); + /*! + \brief Register as a dependent of the DirectX Render System + Resources should call this on construction if they're dependent on the Render System + for survival. Any resources that registers will get callbacks on loss and reset of + device. In addition, callbacks for destruction and creation of the device are also called, + where any resources dependent on the DirectX device should be destroyed and recreated. + \sa Unregister, ID3DResource + */ + void Register(ID3DResource *resource); + + /*! + \brief Unregister as a dependent of the DirectX Render System + Resources should call this on destruction if they're a dependent on the Render System + \sa Register, ID3DResource + */ + void Unregister(ID3DResource *resource); + + virtual void Register(IDispResource *resource); + virtual void Unregister(IDispResource *resource); + protected: virtual void UpdateMonitor(); bool UseWindowedDX(bool fullScreen);