[WinRenderer] Added workaround to fix an issue with color range on some hardware...
authorAnton Fedchin <afedchin@ruswizards.com>
Sat, 26 Dec 2015 08:10:56 +0000 (11:10 +0300)
committerAnton Fedchin <afedchin@ruswizards.com>
Wed, 30 Dec 2015 13:47:15 +0000 (16:47 +0300)
system/shaders/convolution-4x4_d3d.fx
system/shaders/convolution-6x6_d3d.fx
system/shaders/convolutionsep-4x4_d3d.fx
system/shaders/convolutionsep-6x6_d3d.fx
system/shaders/guishader_video.hlsl
system/shaders/guishader_video_control.hlsl
xbmc/cores/VideoRenderers/DXVAHD.cpp
xbmc/cores/VideoRenderers/VideoShaders/WinVideoFilter.cpp
xbmc/cores/VideoRenderers/VideoShaders/WinVideoFilter.h
xbmc/cores/VideoRenderers/WinRenderer.cpp
xbmc/cores/VideoRenderers/WinRenderer.h

index 9d92b12..f7d87b7 100644 (file)
@@ -22,6 +22,7 @@ texture2D g_Texture;
 texture2D g_KernelTexture;
 float2    g_StepXY;
 float2    g_viewPort;
+float2    g_colorRange;
 
 SamplerState RGBSampler : IMMUTABLE
 {
@@ -111,7 +112,7 @@ float4 CONVOLUTION4x4(float2 TextureUV : TEXCOORD0) : SV_TARGET
     getLine(ypos.z, xpos, linetaps) * columntaps.b +
     getLine(ypos.w, xpos, linetaps) * columntaps.a;
 
-  return float4(rgb, 1.0);
+  return float4(g_colorRange.x + g_colorRange.y * saturate(rgb), 1.0);
 }
 
 technique11 SCALER_T
index d6f1210..d2f583a 100644 (file)
@@ -22,6 +22,7 @@ texture2D g_Texture;
 texture2D g_KernelTexture;
 float2    g_StepXY;
 float2    g_viewPort;
+float2    g_colorRange;
 
 SamplerState RGBSampler : IMMUTABLE
 {
@@ -113,7 +114,7 @@ float4 CONVOLUTION6x6(in float2 TextureUV  : TEXCOORD0) : SV_TARGET
                getLine(ypos2.y, xpos1, xpos2, linetaps1, linetaps2) * columntaps1.b +
                getLine(ypos2.z, xpos1, xpos2, linetaps1, linetaps2) * columntaps2.b;
 
-  return float4(rgb, 1.0f);
+  return float4(g_colorRange.x + g_colorRange.y * saturate(rgb), 1.0);
 }
 
 technique11 SCALER_T
index a778987..40c14b6 100644 (file)
@@ -22,6 +22,7 @@ texture2D g_Texture;
 texture2D g_KernelTexture;
 float4    g_StepXY;
 float2    g_viewPort;
+float2    g_colorRange;
 
 SamplerState RGBSampler : IMMUTABLE
 {
@@ -126,7 +127,7 @@ float4 CONVOLUTION4x4Vert(in float2 TextureUV : TEXCOORD0) : SV_TARGET
   float xystart = (-1.0 - f.y) * g_StepXY.w + TextureUV.y;
 
   float4 ypos = xystart + g_StepXY.w * float4(0.0, 1.0, 2.0, 3.0);
-  return float4(getRow(TextureUV.x, ypos, columntaps), 1.0f);
+  return float4(g_colorRange.x + g_colorRange.y * saturate(getRow(TextureUV.x, ypos, columntaps)), 1.0);
 }
 
 technique11 SCALER_T
index bf31f31..3769635 100644 (file)
@@ -22,6 +22,7 @@ texture2D g_Texture;
 texture2D g_KernelTexture;
 float4    g_StepXY;
 float2    g_viewPort;
+float2    g_colorRange;
 
 SamplerState RGBSampler : IMMUTABLE
 {
@@ -139,7 +140,7 @@ float4 CONVOLUTION6x6Vert(in float2 TextureUV : TEXCOORD0) : SV_TARGET
   float3 ypos1 = ystart + g_StepXY.w * float3(0.0, 1.0, 2.0);
   float3 ypos2 = ystart + g_StepXY.w * float3(3.0, 4.0, 5.0);
 
-  return float4(getRow(TextureUV.x, ypos1, ypos2, columntaps1, columntaps2), 1.0);
+  return float4(g_colorRange.x + g_colorRange.y * saturate(getRow(TextureUV.x, ypos1, ypos2, columntaps1, columntaps2)), 1.0);
 }
 
 technique11 SCALER_T
index 938c81f..cf22733 100644 (file)
@@ -32,7 +32,7 @@ SamplerState DynamicSampler : register(s1)
 
 float4 PS(PS_INPUT input) : SV_TARGET
 {
-  return texVideo.Sample(DynamicSampler, input.tex);
+  return adjustColorRange(texVideo.Sample(DynamicSampler, input.tex));
 }
 
 
index ab73268..c4a3556 100644 (file)
@@ -40,7 +40,7 @@ float4 PS(PS_INPUT input) : SV_TARGET
   current.a = input.color.a;
   current.rgb += specular.rgb - 0.5;
 
-  return current;
+  return adjustColorRange(current);
 }
 
 
index c8fd671..470669c 100644 (file)
@@ -337,12 +337,16 @@ bool CProcessorHD::OpenProcessor()
     return false;
   }
 
-  D3D11_VIDEO_PROCESSOR_COLOR_SPACE cs;
-  cs.Usage         = 0;                                          // 0 - Playback, 1 - Processing
-  cs.RGB_Range     = 0;                                          // 0 - Full (0-255), 1 - Limited (16-235)
-  cs.YCbCr_Matrix  = m_flags & CONF_FLAGS_YUVCOEF_BT709 ? 1 : 0; // 0 - BT.601, 1 - BT.709
-  cs.YCbCr_xvYCC   = 1;                                          // 0 - Conventional YCbCr, 1 - xvYCC
-  cs.Nominal_Range = m_flags & CONF_FLAGS_YUV_FULLRANGE ? 2 : 1; // 2 - Full luminance range [0-255], 1 - Studio luminance range [16-235], 0 - driver defaults
+  D3D11_VIDEO_PROCESSOR_COLOR_SPACE cs
+  {
+    0,                                          // 0 - Playback, 1 - Processing
+    0,                                          // 0 - Full (0-255), 1 - Limited (16-235)
+    m_flags & CONF_FLAGS_YUVCOEF_BT709 ? 1 : 0, // 0 - BT.601, 1 - BT.709
+    m_flags & CONF_FLAGS_YUV_FULLRANGE ? 1 : 0, // 0 - Conventional YCbCr, 1 - xvYCC
+    0,                                          // 2 - Full luminance range [0-255], 1 - Studio luminance range [16-235], 0 - driver defaults
+  };
+  if (m_vcaps.DeviceCaps & D3D11_VIDEO_PROCESSOR_DEVICE_CAPS_NOMINAL_RANGE)
+    cs.Nominal_Range = m_flags & CONF_FLAGS_YUV_FULLRANGE ? 2 : 1;
   m_pVideoContext->VideoProcessorSetStreamColorSpace(m_pVideoProcessor, DEFAULT_STREAM_INDEX, &cs);
 
   // Output background color (black)
@@ -696,12 +700,13 @@ bool CProcessorHD::Render(CRect src, CRect dst, ID3D11Resource* target, ID3D11Vi
   // Output rect
   m_pVideoContext->VideoProcessorSetOutputTargetRect(m_pVideoProcessor, TRUE, &dstRECT);
   // Output color space
+  // don't apply any color range conversion, this will be fixed at later stage.
   D3D11_VIDEO_PROCESSOR_COLOR_SPACE colorSpace = {};
   colorSpace.Usage         = 0;  // 0 - playback, 1 - video processing
   colorSpace.RGB_Range     = 0;  // 0 - 0-255, 1 - 16-235
   colorSpace.YCbCr_Matrix  = 1;  // 0 - BT.601, 1 = BT.709
   colorSpace.YCbCr_xvYCC   = 1;  // 0 - Conventional YCbCr, 1 - xvYCC
-  colorSpace.Nominal_Range = g_Windowing.UseLimitedColor() ? 1 : 2;  // 2 - 0-255, 1 = 16-235, 0 - undefined
+  colorSpace.Nominal_Range = 2;  // 2 - 0-255, 1 = 16-235, 0 - undefined
 
   m_pVideoContext->VideoProcessorSetOutputColorSpace(m_pVideoProcessor, &colorSpace);
 
index 2aafd0e..d40b617 100644 (file)
@@ -36,11 +36,12 @@ using namespace DirectX::PackedVector;
 
 CYUV2RGBMatrix::CYUV2RGBMatrix()
 {
-  m_NeedRecalc  = true;
-  m_blacklevel  = 0.0f;
-  m_contrast    = 0.0f;
-  m_flags       = 0;
-  m_format      = RENDER_FMT_NONE;
+  m_NeedRecalc = true;
+  m_blacklevel = 0.0f;
+  m_contrast = 0.0f;
+  m_flags = 0;
+  m_limitedRange = false;
+  m_format = RENDER_FMT_NONE;
 }
 
 void CYUV2RGBMatrix::SetParameters(float contrast, float blacklevel, unsigned int flags, ERenderFormat format)
@@ -65,6 +66,11 @@ void CYUV2RGBMatrix::SetParameters(float contrast, float blacklevel, unsigned in
     m_NeedRecalc = true;
     m_format = format;
   }
+  if (m_limitedRange != g_Windowing.UseLimitedColor())
+  {
+    m_NeedRecalc = true;
+    m_limitedRange = g_Windowing.UseLimitedColor();
+  }
 }
 
 XMFLOAT4X4* CYUV2RGBMatrix::Matrix()
@@ -517,11 +523,12 @@ void CConvolutionShader1Pass::Render(CD3DTexture &sourceTexture,
                                 unsigned int sourceWidth, unsigned int sourceHeight,
                                 unsigned int destWidth, unsigned int destHeight,
                                 CRect sourceRect,
-                                CRect destRect)
+                                CRect destRect,
+                                bool useLimitedRange)
 {
   PrepareParameters(sourceWidth, sourceHeight, sourceRect, destRect);
   float texSteps[] = { 1.0f/(float)sourceWidth, 1.0f/(float)sourceHeight};
-  SetShaderParameters(sourceTexture, &texSteps[0], ARRAY_SIZE(texSteps));
+  SetShaderParameters(sourceTexture, &texSteps[0], ARRAY_SIZE(texSteps), useLimitedRange);
   Execute(nullptr, 4);
 }
 
@@ -568,17 +575,22 @@ void CConvolutionShader1Pass::PrepareParameters(unsigned int sourceWidth, unsign
   }
 }
 
-void CConvolutionShader1Pass::SetShaderParameters(CD3DTexture &sourceTexture, float* texSteps, int texStepsCount)
+void CConvolutionShader1Pass::SetShaderParameters(CD3DTexture &sourceTexture, float* texSteps, int texStepsCount, bool useLimitedRange)
 {
   m_effect.SetTechnique( "SCALER_T" );
   m_effect.SetTexture( "g_Texture",  sourceTexture ) ;
   m_effect.SetTexture( "g_KernelTexture", m_HQKernelTexture );
   m_effect.SetFloatArray("g_StepXY", texSteps, texStepsCount);
-
   UINT numVP = 1;
   D3D11_VIEWPORT viewPort = {};
   g_Windowing.Get3D11Context()->RSGetViewports(&numVP, &viewPort);
   m_effect.SetFloatArray("g_viewPort", &viewPort.Width, 2);
+  float colorRange[2] =
+  {
+    (useLimitedRange ? 16.f : 0.f) / 255.f,
+    (useLimitedRange ? (235.f - 16.f) : 255.f) / 255.f,
+  };
+  m_effect.SetFloatArray("g_colorRange", colorRange, _countof(colorRange));
 }
 
 //==================================================================================
@@ -653,7 +665,8 @@ void CConvolutionShaderSeparable::Render(CD3DTexture &sourceTexture,
                                 unsigned int sourceWidth, unsigned int sourceHeight,
                                 unsigned int destWidth, unsigned int destHeight,
                                 CRect sourceRect,
-                                CRect destRect)
+                                CRect destRect,
+                                bool useLimitedRange)
 {
   if(m_destWidth != destWidth || m_sourceHeight != sourceHeight)
     CreateIntermediateRenderTarget(destWidth, sourceHeight);
@@ -666,7 +679,7 @@ void CConvolutionShaderSeparable::Render(CD3DTexture &sourceTexture,
     1.0f / static_cast<float>(destWidth), 
     1.0f / static_cast<float>(sourceHeight)
   };
-  SetShaderParameters(sourceTexture, texSteps, 4);
+  SetShaderParameters(sourceTexture, texSteps, 4, useLimitedRange);
 
   Execute(nullptr, 4);
 
@@ -808,12 +821,18 @@ void CConvolutionShaderSeparable::PrepareParameters(unsigned int sourceWidth, un
   }
 }
 
-void CConvolutionShaderSeparable::SetShaderParameters(CD3DTexture &sourceTexture, float* texSteps, int texStepsCount)
+void CConvolutionShaderSeparable::SetShaderParameters(CD3DTexture &sourceTexture, float* texSteps, int texStepsCount, bool useLimitedRange)
 {
   m_effect.SetTechnique( "SCALER_T" );
   m_effect.SetTexture( "g_Texture",  sourceTexture );
   m_effect.SetTexture( "g_KernelTexture", m_HQKernelTexture );
   m_effect.SetFloatArray("g_StepXY", texSteps, texStepsCount);
+  float colorRange[2] =
+  {
+    (useLimitedRange ? 16.f : 0.f) / 255.f,
+    (useLimitedRange ? (235.f - 16.f) : 255.f) / 255.f,
+  };
+  m_effect.SetFloatArray("g_colorRange", colorRange, _countof(colorRange));
 }
 
 void CConvolutionShaderSeparable::SetStepParams(UINT iPass)
index e6bbd44..294018b 100644 (file)
@@ -41,6 +41,7 @@ private:
   float        m_contrast;
   float        m_blacklevel;
   unsigned int m_flags;
+  bool         m_limitedRange;
   ERenderFormat m_format;
   XMFLOAT4X4   m_mat;
 };
@@ -122,7 +123,8 @@ public:
                                unsigned int sourceWidth, unsigned int sourceHeight,
                                unsigned int destWidth, unsigned int destHeight,
                                CRect sourceRect,
-                               CRect destRect) = 0;
+                               CRect destRect,
+                               bool useLimitedRange) = 0;
   CConvolutionShader() : CWinShader() {}
   virtual ~CConvolutionShader();
 
@@ -149,14 +151,15 @@ public:
                                unsigned int sourceWidth, unsigned int sourceHeight,
                                unsigned int destWidth, unsigned int destHeight,
                                CRect sourceRect,
-                               CRect destRect);
+                               CRect destRect,
+                               bool useLimitedRange);
   CConvolutionShader1Pass() : CConvolutionShader(), m_sourceWidth(0), m_sourceHeight(0) {}
 
 protected:
   virtual void PrepareParameters(unsigned int sourceWidth, unsigned int sourceHeight,
                                CRect sourceRect,
                                CRect destRect);
-  virtual void SetShaderParameters(CD3DTexture &sourceTexture, float* texSteps, int texStepsCount);
+  virtual void SetShaderParameters(CD3DTexture &sourceTexture, float* texSteps, int texStepsCount, bool useLimitedRange);
 
 
 private:
@@ -173,7 +176,8 @@ public:
                                unsigned int sourceWidth, unsigned int sourceHeight,
                                unsigned int destWidth, unsigned int destHeight,
                                CRect sourceRect,
-                               CRect destRect);
+                               CRect destRect,
+                               bool useLimitedRange);
   virtual ~CConvolutionShaderSeparable();
 
 protected:
@@ -184,7 +188,7 @@ protected:
                                unsigned int destWidth, unsigned int destHeight,
                                CRect sourceRect,
                                CRect destRect);
-  virtual void SetShaderParameters(CD3DTexture &sourceTexture, float* texSteps, int texStepsCount);
+  virtual void SetShaderParameters(CD3DTexture &sourceTexture, float* texSteps, int texStepsCount, bool useLimitedRange);
   virtual void SetStepParams(UINT stepIndex);
 
 private:
index e7e82a2..2721189 100644 (file)
@@ -83,7 +83,6 @@ CWinRenderer::CWinRenderer()
   m_destWidth = 0;
   m_destHeight = 0;
   m_bConfigured = false;
-  m_clearColour = 0;
   m_format = RENDER_FMT_NONE;
   m_processor = nullptr;
   m_neededBuffers = 0;
@@ -355,12 +354,8 @@ void CWinRenderer::Update()
 void CWinRenderer::RenderUpdate(bool clear, DWORD flags, DWORD alpha)
 {
   if (clear)
-    g_graphicsContext.Clear(m_clearColour);
-
-  if (alpha < 255)
-    g_Windowing.SetAlphaBlendEnable(true);
-  else
-    g_Windowing.SetAlphaBlendEnable(false);
+    g_graphicsContext.Clear(g_Windowing.UseLimitedColor() ? 0x101010 : 0);
+  g_Windowing.SetAlphaBlendEnable(alpha < 255);
 
   if (!m_bConfigured) 
     return;
@@ -368,9 +363,7 @@ void CWinRenderer::RenderUpdate(bool clear, DWORD flags, DWORD alpha)
   ManageTextures();
 
   CSingleLock lock(g_graphicsContext);
-
   ManageDisplay();
-
   Render(flags);
 }
 
@@ -406,9 +399,6 @@ unsigned int CWinRenderer::PreInit()
   if ( m_resolution == RES_WINDOW )
     m_resolution = RES_DESKTOP;
 
-  // setup the background colour
-  m_clearColour = (g_advancedSettings.m_videoBlackBarColour & 0xff) * 0x010101;
-
   m_formats.clear();
   m_formats.push_back(RENDER_FMT_YUV420P);
 
@@ -824,8 +814,9 @@ void CWinRenderer::Stage1()
   CRect destRect = m_bUseHQScaler ? m_sourceRect : g_graphicsContext.StereoCorrection(m_destRect);
   // select target view 
   ID3D11RenderTargetView* pRTView = m_bUseHQScaler ? m_IntermediateTarget.GetRenderTarget() : oldRTView;
-  // set destination render target
-  pContext->OMSetRenderTargets(1, &pRTView, nullptr);
+  // change destination for HQ scallers
+  if (m_bUseHQScaler)
+    pContext->OMSetRenderTargets(1, &pRTView, nullptr);
   // get rendertarget's dimension
   if (pRTView)
   {
@@ -837,7 +828,7 @@ void CWinRenderer::Stage1()
     {
       D3D11_TEXTURE2D_DESC desc;
       pTexture->GetDesc(&desc);
-      viewPort = CD3D11_VIEWPORT(0.0f, 0.0f, desc.Width, desc.Height);
+      viewPort = CD3D11_VIEWPORT(0.0f, 0.0f, static_cast<float>(desc.Width), static_cast<float>(desc.Height));
     }
     SAFE_RELEASE(pResource);
     SAFE_RELEASE(pTexture);
@@ -855,14 +846,17 @@ void CWinRenderer::Stage1()
   // Restore our view port.
   g_Windowing.RestoreViewPort();
   // Restore the render target and depth view.
-  pContext->OMSetRenderTargets(1, &oldRTView, oldDSView);
+  if (m_bUseHQScaler)
+    pContext->OMSetRenderTargets(1, &oldRTView, oldDSView);
   SAFE_RELEASE(oldRTView);
   SAFE_RELEASE(oldDSView);
 }
 
 void CWinRenderer::Stage2()
 {
-  m_scalerShader->Render(m_IntermediateTarget, m_sourceWidth, m_sourceHeight, m_destWidth, m_destHeight, m_sourceRect, g_graphicsContext.StereoCorrection(m_destRect));
+  m_scalerShader->Render(m_IntermediateTarget, m_sourceWidth, m_sourceHeight, m_destWidth, m_destHeight
+                       , m_sourceRect, g_graphicsContext.StereoCorrection(m_destRect)
+                       , (m_renderMethod == RENDER_DXVA && g_Windowing.UseLimitedColor()));
 }
 
 void CWinRenderer::RenderProcessor(DWORD flags)
@@ -873,27 +867,6 @@ void CWinRenderer::RenderProcessor(DWORD flags)
   if (!image->pic)
     return;
 
-  ID3D11Resource* target;
-  if ( m_bUseHQScaler 
-    || g_graphicsContext.GetStereoMode() == RENDER_STEREO_MODE_ANAGLYPH_RED_CYAN
-    || g_graphicsContext.GetStereoMode() == RENDER_STEREO_MODE_ANAGLYPH_GREEN_MAGENTA
-    || g_graphicsContext.GetStereoMode() == RENDER_STEREO_MODE_ANAGLYPH_YELLOW_BLUE
-    || true /* workaround for some GPUs */)
-  {
-    target = m_IntermediateTarget.Get();
-    target->AddRef();
-  }
-  else // dead code.
-  {
-    ID3D11RenderTargetView* rtv = nullptr;
-    g_Windowing.Get3D11Context()->OMGetRenderTargets(1, &rtv, nullptr);
-    if (rtv)
-    {
-      rtv->GetResource(&target);
-      rtv->Release();
-    }
-  }
-
   int past = 0;
   int future = 0;
   DXVABuffer **buffers = (DXVABuffer**)m_VideoBuffers;
@@ -936,22 +909,18 @@ void CWinRenderer::RenderProcessor(DWORD flags)
       break;
   }
 
-  m_processor->Render(m_sourceRect, destRect, target, views, flags, image->frameIdx);
+  m_processor->Render(m_sourceRect, destRect, m_IntermediateTarget.Get(), views, flags, image->frameIdx);
   
   if (m_bUseHQScaler)
   {
     Stage2();
   }
-  // uncomment when workaround removed
-  else /*if ( g_graphicsContext.GetStereoMode() == RENDER_STEREO_MODE_ANAGLYPH_RED_CYAN
-         || g_graphicsContext.GetStereoMode() == RENDER_STEREO_MODE_ANAGLYPH_GREEN_MAGENTA
-         || g_graphicsContext.GetStereoMode() == RENDER_STEREO_MODE_ANAGLYPH_YELLOW_BLUE)*/
+  else
   {
     // texels
     CRect tu = { destRect.x1 / m_destWidth, destRect.y1 / m_destHeight, destRect.x2 / m_destWidth, destRect.y2 / m_destHeight };
-    CD3DTexture::DrawQuad(m_destRect, 0, &m_IntermediateTarget, &tu, SHADER_METHOD_RENDER_TEXTURE_NOBLEND);
+    CD3DTexture::DrawQuad(m_destRect, 0xFFFFFFFF, &m_IntermediateTarget, &tu, SHADER_METHOD_RENDER_TEXTURE_BLEND);
   }
-  SAFE_RELEASE(target);
 }
 
 bool CWinRenderer::RenderCapture(CRenderCapture* capture)
index 79fa33e..b7fe5f3 100644 (file)
@@ -219,26 +219,18 @@ protected:
   // PS rendering
   bool                 m_bUseHQScaler;
   CD3DTexture          m_IntermediateTarget;
-
   CYUV2RGBShader*      m_colorShader;
   CConvolutionShader*  m_scalerShader;
-
   ESCALINGMETHOD       m_scalingMethod;
   ESCALINGMETHOD       m_scalingMethodGui;
-
   bool                 m_bFilterInitialized;
 
   int                  m_iRequestedMethod;
-
-  // clear colour for "black" bars
-  DWORD                m_clearColour;
   unsigned int         m_extended_format;
-
   // Width and height of the render target
   // the separable HQ scalers need this info, but could the m_destRect be used instead?
   unsigned int         m_destWidth;
   unsigned int         m_destHeight;
-
   int                  m_neededBuffers;
   unsigned int         m_frameIdx;
 };