From cf695568c9add858c114673463b44d2921c5894a Mon Sep 17 00:00:00 2001 From: Istvan Stikrad Date: Thu, 26 Apr 2012 15:20:43 +0200 Subject: [PATCH] [added] Shader based HQ scalers for DXVA renderer --- xbmc/cores/VideoRenderers/WinRenderer.cpp | 80 +++++++++++++++++++++++------ xbmc/cores/VideoRenderers/WinRenderer.h | 1 + 2 files changed, 64 insertions(+), 17 deletions(-) diff --git a/xbmc/cores/VideoRenderers/WinRenderer.cpp b/xbmc/cores/VideoRenderers/WinRenderer.cpp index 55d29a6..544fbb1 100644 --- a/xbmc/cores/VideoRenderers/WinRenderer.cpp +++ b/xbmc/cores/VideoRenderers/WinRenderer.cpp @@ -315,6 +315,19 @@ void CWinRenderer::Update(bool bPauseDrawing) ManageDisplay(); } +void CWinRenderer::FlushGPU() +{ + LPDIRECT3DDEVICE9 pD3DDevice = g_Windowing.Get3DDevice(); + IDirect3DQuery9* pEvent = NULL; + + pD3DDevice->CreateQuery(D3DQUERYTYPE_EVENT, &pEvent); + if (pEvent != NULL) + { + pEvent->Issue(D3DISSUE_END); + while (S_FALSE == pEvent->GetData(NULL, 0, D3DGETDATA_FLUSH)) Sleep(1); + } +} + void CWinRenderer::RenderUpdate(bool clear, DWORD flags, DWORD alpha) { LPDIRECT3DDEVICE9 pD3DDevice = g_Windowing.Get3DDevice(); @@ -441,7 +454,15 @@ bool CWinRenderer::CreateIntermediateRenderTarget() CLog::Log(LOGDEBUG, __FUNCTION__": format %i", format); - if(!m_IntermediateTarget.Create(m_sourceWidth, m_sourceHeight, 1, usage, format, D3DPOOL_DEFAULT)) + if (m_renderMethod == RENDER_DXVA) + { + if(!m_IntermediateTarget.Create(m_sourceWidth, m_sourceHeight, 1, usage, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT)) + { + CLog::Log(LOGERROR, __FUNCTION__": Failed to create render target texture. Going back to DXVA hardware scaling."); + return false; + } + } + else if(!m_IntermediateTarget.Create(m_sourceWidth, m_sourceHeight, 1, usage, format, D3DPOOL_DEFAULT)) { CLog::Log(LOGERROR, __FUNCTION__": render target creation failed. Going back to bilinear scaling.", format); return false; @@ -511,7 +532,12 @@ void CWinRenderer::SelectPSVideoFilter() bool scaleUp = (int)m_sourceHeight < g_graphicsContext.GetHeight() && (int)m_sourceWidth < g_graphicsContext.GetWidth(); bool scaleFps = m_fps < (g_advancedSettings.m_videoAutoScaleMaxFps + 0.01f); - if (Supports(VS_SCALINGMETHOD_LANCZOS3_FAST) && scaleSD && scaleUp && scaleFps) + if (m_renderMethod == RENDER_DXVA) + { + m_scalingMethod = VS_SCALINGMETHOD_DXVA_HARDWARE; + m_bUseHQScaler = false; + } + else if (Supports(VS_SCALINGMETHOD_LANCZOS3_FAST) && scaleSD && scaleUp && scaleFps) { m_scalingMethod = VS_SCALINGMETHOD_LANCZOS3_FAST; m_bUseHQScaler = true; @@ -559,6 +585,10 @@ void CWinRenderer::UpdatePSVideoFilter() SAFE_DELETE(m_colorShader); + // When using DXVA, we are already setup at this point, color shader is not needed + if (m_renderMethod == RENDER_DXVA) + return; + if (m_bUseHQScaler) { m_colorShader = new CYUV2RGBShader(); @@ -604,14 +634,11 @@ void CWinRenderer::UpdateVideoFilter() break; case RENDER_PS: + case RENDER_DXVA: SelectPSVideoFilter(); UpdatePSVideoFilter(); break; - case RENDER_DXVA: - // Everything already setup, nothing to do. - break; - default: return; } @@ -621,6 +648,9 @@ void CWinRenderer::Render(DWORD flags) { if (m_renderMethod == RENDER_DXVA) { + UpdateVideoFilter(); + if (m_bUseHQScaler) + FlushGPU(); CWinRenderer::RenderProcessor(flags); return; } @@ -902,19 +932,38 @@ void CWinRenderer::RenderProcessor(DWORD flags) { CSingleLock lock(g_graphicsContext); HRESULT hr; + CRect destRect; + + if (m_bUseHQScaler) + { + destRect.y1 = 0.0f; + destRect.y2 = m_sourceHeight; + destRect.x1 = 0.0f; + destRect.x2 = m_sourceWidth; + } + else + destRect = m_destRect; DXVABuffer *image = (DXVABuffer*)m_VideoBuffers[m_iYV12RenderBuffer]; IDirect3DSurface9* target; - if(FAILED(hr = g_Windowing.Get3DDevice()->GetRenderTarget(0, &target))) + if (m_bUseHQScaler) + m_IntermediateTarget.GetSurfaceLevel(0, &target); + else { - CLog::Log(LOGERROR, "CWinRenderer::RenderSurface - failed to get render target. %s", CRenderSystemDX::GetErrorDescription(hr).c_str()); - return; + if(FAILED(hr = g_Windowing.Get3DDevice()->GetRenderTarget(0, &target))) + { + CLog::Log(LOGERROR, "CWinRenderer::RenderSurface - failed to get render target. %s", CRenderSystemDX::GetErrorDescription(hr).c_str()); + return; + } } - m_processor.Render(m_sourceRect, m_destRect, target, image->id, flags); + m_processor.Render(m_sourceRect, destRect, target, image->id, flags); target->Release(); + + if (m_bUseHQScaler) + Stage2(); } bool CWinRenderer::RenderCapture(CRenderCapture* capture) @@ -1038,17 +1087,14 @@ bool CWinRenderer::Supports(ERENDERFEATURE feature) bool CWinRenderer::Supports(ESCALINGMETHOD method) { - if (m_renderMethod == RENDER_DXVA) + if (m_renderMethod == RENDER_PS || m_renderMethod == RENDER_DXVA) { - if(method == VS_SCALINGMETHOD_DXVA_HARDWARE) + if(m_renderMethod == RENDER_DXVA && method == VS_SCALINGMETHOD_DXVA_HARDWARE) return true; - return false; - } - else if(m_renderMethod == RENDER_PS) - { + if(m_deviceCaps.PixelShaderVersion >= D3DPS_VERSION(2, 0) && ( method == VS_SCALINGMETHOD_AUTO - || method == VS_SCALINGMETHOD_LINEAR)) + || (method == VS_SCALINGMETHOD_LINEAR && m_renderMethod == RENDER_PS) )) return true; if(m_deviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0)) diff --git a/xbmc/cores/VideoRenderers/WinRenderer.h b/xbmc/cores/VideoRenderers/WinRenderer.h index 84f33b2..ed19650 100644 --- a/xbmc/cores/VideoRenderers/WinRenderer.h +++ b/xbmc/cores/VideoRenderers/WinRenderer.h @@ -179,6 +179,7 @@ class CWinRenderer : public CBaseRenderer virtual unsigned int GetProcessorSize() { return m_processor.Size(); } protected: + void FlushGPU(); virtual void Render(DWORD flags); void RenderSW(); void RenderPS(); -- 1.7.10