Merge pull request #4264 from jmarshallnz/scrollfix
[vuplus_xbmc] / system / shaders / yuv2rgb_basic.glsl
1 /*
2  *      Copyright (C) 2010-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  */
20
21 #if(XBMC_texture_rectangle)
22 # extension GL_ARB_texture_rectangle : enable
23 # define texture2D texture2DRect
24 # define sampler2D sampler2DRect
25 #endif
26
27 uniform sampler2D m_sampY;
28 uniform sampler2D m_sampU;
29 uniform sampler2D m_sampV;
30 varying vec2      m_cordY;
31 varying vec2      m_cordU;
32 varying vec2      m_cordV;
33
34 uniform vec2      m_step;
35
36 uniform mat4      m_yuvmat;
37
38 uniform float     m_stretch;
39
40 vec2 stretch(vec2 pos)
41 {
42 #if (XBMC_STRETCH)
43   // our transform should map [0..1] to itself, with f(0) = 0, f(1) = 1, f(0.5) = 0.5, and f'(0.5) = b.
44   // a simple curve to do this is g(x) = b(x-0.5) + (1-b)2^(n-1)(x-0.5)^n + 0.5
45   // where the power preserves sign. n = 2 is the simplest non-linear case (required when b != 1)
46   #if(XBMC_texture_rectangle)
47     float x = (pos.x * m_step.x) - 0.5;
48     return vec2((mix(2.0 * x * abs(x), x, m_stretch) + 0.5) / m_step.x, pos.y);
49   #else
50     float x = pos.x - 0.5;
51     return vec2(mix(2.0 * x * abs(x), x, m_stretch) + 0.5, pos.y);
52   #endif
53 #else
54   return pos;
55 #endif
56 }
57
58 void main()
59 {
60 #if defined(XBMC_YV12) || defined(XBMC_NV12)
61
62   vec4 yuv, rgb;
63   yuv.rgba = vec4( texture2D(m_sampY, stretch(m_cordY)).r
64                  , texture2D(m_sampU, stretch(m_cordU)).g
65                  , texture2D(m_sampV, stretch(m_cordV)).a
66                  , 1.0 );
67
68   rgb   = m_yuvmat * yuv;
69   rgb.a = gl_Color.a;
70   gl_FragColor = rgb;
71
72 #elif defined(XBMC_VDPAU_NV12)
73
74   vec4 yuv, rgb;
75   yuv.rgba = vec4( texture2D(m_sampY, stretch(m_cordY)).r
76                  , texture2D(m_sampU, stretch(m_cordU)).r
77                  , texture2D(m_sampV, stretch(m_cordV)).g
78                  , 1.0 );
79
80   rgb   = m_yuvmat * yuv;
81   rgb.a = gl_Color.a;
82   gl_FragColor = rgb;
83
84 #elif defined(XBMC_YUY2) || defined(XBMC_UYVY)
85
86 #if(XBMC_texture_rectangle)
87   vec2 stepxy = vec2(1.0, 1.0);
88   vec2 pos    = stretch(m_cordY);
89   pos         = vec2(pos.x - 0.25, pos.y);
90   vec2 f      = fract(pos);
91 #else
92   vec2 stepxy = m_step;
93   vec2 pos    = stretch(m_cordY);
94   pos         = vec2(pos.x - stepxy.x * 0.25, pos.y);
95   vec2 f      = fract(pos / stepxy);
96 #endif
97
98   //y axis will be correctly interpolated by opengl
99   //x axis will not, so we grab two pixels at the center of two columns and interpolate ourselves
100   vec4 c1 = texture2D(m_sampY, vec2(pos.x + (0.5 - f.x) * stepxy.x, pos.y));
101   vec4 c2 = texture2D(m_sampY, vec2(pos.x + (1.5 - f.x) * stepxy.x, pos.y));
102
103   /* each pixel has two Y subpixels and one UV subpixel
104      YUV  Y  YUV
105      check if we're left or right of the middle Y subpixel and interpolate accordingly*/
106 #ifdef XBMC_YUY2 //BGRA = YUYV
107   float leftY   = mix(c1.b, c1.r, f.x * 2.0);
108   float rightY  = mix(c1.r, c2.b, f.x * 2.0 - 1.0);
109   vec2  outUV   = mix(c1.ga, c2.ga, f.x);
110 #else //BGRA = UYVY
111   float leftY   = mix(c1.g, c1.a, f.x * 2.0);
112   float rightY  = mix(c1.a, c2.g, f.x * 2.0 - 1.0);
113   vec2  outUV   = mix(c1.br, c2.br, f.x);
114 #endif //XBMC_YUY2
115
116   float outY    = mix(leftY, rightY, step(0.5, f.x));
117
118   vec4  yuv     = vec4(outY, outUV, 1.0);
119   vec4  rgb     = m_yuvmat * yuv;
120
121   gl_FragColor   = rgb;
122   gl_FragColor.a = gl_Color.a;
123
124 #endif
125 }