Merge pull request #25955 from neo1973/improve_wayland_scaling
[xbmc.git] / system / shaders / yuv2rgb_d3d.fx
blobc52996068d62eca22233f8f02e4258ead16b47f8
1 /*
2  *      Copyright (C) 2005-2013 Team XBMC
3  *      http://xbmc.org
4  *
5  *  This Program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This Program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with XBMC; see the file COPYING.  If not, see
17  *  <http://www.gnu.org/licenses/>.
18  *
19  */
21 #include "output_d3d.fx"
23 texture2D  g_Texture[3];
24 float4x4   g_ColorMatrix;
25 float2     g_StepXY;
26 float2     g_viewPort;
27 float4x4   g_primMat;
28 float      g_gammaDstInv;
29 float      g_gammaSrc;
31 SamplerState YUVSampler : IMMUTABLE
33   AddressU = CLAMP;
34   AddressV = CLAMP;
35   Filter   = MIN_MAG_MIP_LINEAR;
38 struct VS_INPUT
40   float4 Position   : POSITION;
41   float2 TextureY   : TEXCOORD0;
42   float2 TextureUV  : TEXCOORD1;
45 struct VS_OUTPUT
47   float2 TextureY   : TEXCOORD0;
48   float2 TextureUV  : TEXCOORD1;
49   float4 Position   : SV_POSITION;
52 VS_OUTPUT VS(VS_INPUT In)
54   VS_OUTPUT output = (VS_OUTPUT)0;
55   output.Position.x =  (In.Position.x / (g_viewPort.x  / 2.0)) - 1;
56   output.Position.y = -(In.Position.y / (g_viewPort.y / 2.0)) + 1;
57   output.Position.z = output.Position.z;
58   output.Position.w = 1.0;
59   output.TextureY   = In.TextureY;
60   output.TextureUV  = In.TextureUV;
62   return output;
65 #ifdef NV12_SNORM_UV
66 inline float unormU(float c)
68   c *= 0.5;
69   if (c < 0.0) c += 1.0;
70   return saturate(c);
72 inline float2 unormUV(float2 rg)
74   return float2(unormU(rg.x), unormU(rg.y));
76 #endif
78 float4 YUV2RGB(VS_OUTPUT In) : SV_TARGET
80 #if defined(XBMC_YV12) //|| defined(XBMC_NV12)
81   float4 YUV = float4(g_Texture[0].Sample(YUVSampler, In.TextureY ).r
82                     , g_Texture[1].Sample(YUVSampler, In.TextureUV).r
83                     , g_Texture[2].Sample(YUVSampler, In.TextureUV).r
84                     , 1.0);
85 #elif defined(XBMC_NV12)
86   float4 YUV = float4(g_Texture[0].Sample(YUVSampler, In.TextureY).r
87   #if defined(NV12_SNORM_UV)
88                     , unormUV(g_Texture[1].Sample(YUVSampler, In.TextureUV).rg)
89   #else
90                     , g_Texture[1].Sample(YUVSampler, In.TextureUV).rg
91   #endif
92                     , 1.0);
93 #elif defined(XBMC_YUY2) || defined(XBMC_UYVY)
94   // The HLSL compiler is smart enough to optimize away these redundant assignments.
95   // That way the code is almost identical to the OGL shader.
96   float2 stepxy = g_StepXY;
97   float2 pos    = In.TextureY;
98   pos           = float2(pos.x - (stepxy.x * 0.25), pos.y);
99   float2 f      = frac(pos / stepxy);
101   //y axis will be correctly interpolated by opengl
102   //x axis will not, so we grab two pixels at the center of two columns and interpolate ourselves
103   float4 c1 = g_Texture[0].Sample(YUVSampler, float2(pos.x + ((0.5 - f.x) * stepxy.x), pos.y));
104   float4 c2 = g_Texture[0].Sample(YUVSampler, float2(pos.x + ((1.5 - f.x) * stepxy.x), pos.y));
106   /* each pixel has two Y subpixels and one UV subpixel
107       YUV  Y  YUV
108       check if we're left or right of the middle Y subpixel and interpolate accordingly*/
109   #if defined(XBMC_YUY2) // BGRA = YUYV
110     float  leftY  = lerp(c1.b, c1.r, f.x * 2.0);
111     float  rightY = lerp(c1.r, c2.b, f.x * 2.0 - 1.0);
112     float2 outUV  = lerp(c1.ga, c2.ga, f.x);
113   #elif defined(XBMC_UYVY) // BGRA = UYVY
114     float  leftY  = lerp(c1.g, c1.a, f.x * 2.0);
115     float  rightY = lerp(c1.a, c2.g, f.x * 2.0 - 1.0);
116     float2 outUV  = lerp(c1.br, c2.br, f.x);
117   #endif
118     float  outY   = lerp(leftY, rightY, step(0.5, f.x));
119     float4 YUV    = float4(outY, outUV, 1.0);
120 #endif
122   float4 rgb = mul(YUV, g_ColorMatrix);
123 #if defined(XBMC_COL_CONVERSION)
124   rgb.rgb = pow(max(0.0, rgb.rgb), g_gammaSrc);
125   rgb.rgb = max(0.0, mul(rgb, g_primMat).rgb);
126   rgb.rgb = pow(rgb.rgb, g_gammaDstInv);
127 #endif
128   return output4(rgb, In.TextureY);
131 technique11 YUV2RGB_T
133   pass P0
134   {
135     SetVertexShader( CompileShader( vs_4_0_level_9_1, VS() ) );
136     SetPixelShader( CompileShader( ps_4_0_level_9_1, YUV2RGB() ) );
137   }