mixer: fix lowering hw volume while muted
[mplayer.git] / libvo / vo_gl3_shaders.glsl
blobf67e55e6f5b4210558d2e6b9181553b3d6607f86
1 /*
2  * This file is part of mplayer2.
3  *
4  * mplayer2 is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * mplayer2 is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with mplayer2; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  */
19 // Note that this file is not directly passed as shader, but run through some
20 // text processing functions, and in fact contains multiple vertex and fragment
21 // shaders.
23 // inserted at the beginning of all shaders
24 #!section prelude
25 #!section vertex_all
26 uniform mat3 transform;
27 uniform sampler3D lut_3d;
29 in vec2 vertex_position;
30 in vec4 vertex_color;
31 out vec4 color;
32 in vec2 vertex_texcoord;
33 out vec2 texcoord;
35 void main() {
36     vec3 position = vec3(vertex_position, 1);
37 #ifndef FIXED_SCALE
38     position = transform * position;
39 #endif
40     gl_Position = vec4(position, 1);
41     color = vertex_color;
42 #ifdef USE_3DLUT
43     color = vec4(texture(lut_3d, color.rgb).rgb, color.a);
44 #endif
45     texcoord = vertex_texcoord;
48 #!section frag_eosd
49 uniform sampler2D texture1;
51 in vec2 texcoord;
52 in vec4 color;
53 out vec4 out_color;
55 void main() {
56     out_color = vec4(color.rgb, color.a * texture(texture1, texcoord).r);
59 #!section frag_osd
60 uniform sampler2D texture1;
62 in vec2 texcoord;
63 in vec4 color;
64 out vec4 out_color;
66 void main() {
67     out_color = texture(texture1, texcoord).rrrg * color;
70 #!section frag_video
71 uniform sampler2D texture1;
72 uniform sampler2D texture2;
73 uniform sampler2D texture3;
74 uniform sampler1D lut_c_1d;
75 uniform sampler1D lut_l_1d;
76 uniform sampler2D lut_c_2d;
77 uniform sampler2D lut_l_2d;
78 uniform sampler3D lut_3d;
79 uniform sampler2D dither;
80 uniform mat4x3 colormatrix;
81 uniform vec3 inv_gamma;
82 uniform float conv_gamma;
83 uniform float dither_quantization;
84 uniform float dither_multiply;
85 uniform float filter_param1;
87 in vec2 texcoord;
88 out vec4 out_color;
90 vec4 sample_bilinear(sampler2D tex, vec2 texcoord) {
91     return texture(tex, texcoord);
94 // Explanation how bicubic scaling with only 4 texel fetches is done:
95 //   http://www.mate.tue.nl/mate/pdfs/10318.pdf
96 //   'Efficient GPU-Based Texture Interpolation using Uniform B-Splines'
97 // Explanation why this algorithm normally always blurs, even with unit scaling:
98 //   http://bigwww.epfl.ch/preprints/ruijters1001p.pdf
99 //   'GPU Prefilter for Accurate Cubic B-spline Interpolation'
100 vec4 calcweights(float s) {
101     vec4 t = vec4(-0.5, 0.1666, 0.3333, -0.3333) * s + vec4(1, 0, -0.5, 0.5);
102     t = t * s + vec4(0, 0, -0.5, 0.5);
103     t = t * s + vec4(-0.6666, 0, 0.8333, 0.1666);
104     vec2 a = vec2(1 / t.z, 1 / t.w);
105     t.xy = t.xy * a + vec2(1, 1);
106     t.x = t.x + s;
107     t.y = t.y - s;
108     return t;
111 vec4 sample_bicubic_fast(sampler2D tex, vec2 texcoord) {
112     vec2 texsize = textureSize(tex, 0);
113     vec2 pt = 1 / texsize;
114     vec2 fcoord = fract(texcoord * texsize + vec2(0.5, 0.5));
115     vec4 parmx = calcweights(fcoord.x);
116     vec4 parmy = calcweights(fcoord.y);
117     vec4 cdelta;
118     cdelta.xz = parmx.rg * vec2(-pt.x, pt.x);
119     cdelta.yw = parmy.rg * vec2(-pt.y, pt.y);
120     // first y-interpolation
121     vec4 ar = texture(tex, texcoord + cdelta.xy);
122     vec4 ag = texture(tex, texcoord + cdelta.xw);
123     vec4 ab = mix(ag, ar, parmy.b);
124     // second y-interpolation
125     vec4 br = texture(tex, texcoord + cdelta.zy);
126     vec4 bg = texture(tex, texcoord + cdelta.zw);
127     vec4 aa = mix(bg, br, parmy.b);
128     // x-interpolation
129     return mix(aa, ab, parmx.b);
132 float[2] weights2(sampler1D lookup, float f) {
133     vec4 c = texture(lookup, f);
134     return float[2](c.r, c.g);
137 float[4] weights4(sampler1D lookup, float f) {
138     vec4 c = texture(lookup, f);
139     return float[4](c.r, c.g, c.b, c.a);
142 float[6] weights6(sampler2D lookup, float f) {
143     vec4 c1 = texture(lookup, vec2(0.25, f));
144     vec4 c2 = texture(lookup, vec2(0.75, f));
145     return float[6](c1.r, c1.g, c1.b, c2.r, c2.g, c2.b);
148 float[8] weights8(sampler2D lookup, float f) {
149     vec4 c1 = texture(lookup, vec2(0.25, f));
150     vec4 c2 = texture(lookup, vec2(0.75, f));
151     return float[8](c1.r, c1.g, c1.b, c1.a, c2.r, c2.g, c2.b, c2.a);
154 float[12] weights12(sampler2D lookup, float f) {
155     vec4 c1 = texture(lookup, vec2(1.0/6.0, f));
156     vec4 c2 = texture(lookup, vec2(0.5, f));
157     vec4 c3 = texture(lookup, vec2(5.0/6.0, f));
158     return float[12](c1.r, c1.g, c1.b, c1.a,
159                      c2.r, c2.g, c2.b, c2.a,
160                      c3.r, c3.g, c3.b, c3.a);
163 float[16] weights16(sampler2D lookup, float f) {
164     vec4 c1 = texture(lookup, vec2(0.125, f));
165     vec4 c2 = texture(lookup, vec2(0.375, f));
166     vec4 c3 = texture(lookup, vec2(0.625, f));
167     vec4 c4 = texture(lookup, vec2(0.875, f));
168     return float[16](c1.r, c1.g, c1.b, c1.a, c2.r, c2.g, c2.b, c2.a,
169                      c3.r, c3.g, c3.b, c3.a, c4.r, c4.g, c4.b, c4.a);
172 #define CONVOLUTION_SEP_N(NAME, N)                                           \
173     vec4 NAME(sampler2D tex, vec2 texcoord, vec2 pt, float weights[N]) {     \
174         vec4 res = vec4(0);                                                  \
175         for (int n = 0; n < N; n++) {                                        \
176             res += weights[n] * texture(tex, texcoord + pt * n);             \
177         }                                                                    \
178         return res;                                                          \
179     }
181 CONVOLUTION_SEP_N(convolution_sep2, 2)
182 CONVOLUTION_SEP_N(convolution_sep4, 4)
183 CONVOLUTION_SEP_N(convolution_sep6, 6)
184 CONVOLUTION_SEP_N(convolution_sep8, 8)
185 CONVOLUTION_SEP_N(convolution_sep12, 12)
186 CONVOLUTION_SEP_N(convolution_sep16, 16)
188 // The dir parameter is (0, 1) or (1, 0), and we expect the shader compiler to
189 // remove all the redundant multiplications and additions.
190 #define SAMPLE_CONVOLUTION_SEP_N(NAME, N, SAMPLERT, CONV_FUNC, WEIGHTS_FUNC)\
191     vec4 NAME(vec2 dir, SAMPLERT lookup, sampler2D tex, vec2 texcoord) {    \
192         vec2 texsize = textureSize(tex, 0);                                 \
193         vec2 pt = (1 / texsize) * dir;                                      \
194         float fcoord = dot(fract(texcoord * texsize - 0.5), dir);           \
195         vec2 base = texcoord - fcoord * pt;                                 \
196         return CONV_FUNC(tex, base - pt * (N / 2 - 1), pt,                  \
197                          WEIGHTS_FUNC(lookup, fcoord));                     \
198     }
200 SAMPLE_CONVOLUTION_SEP_N(sample_convolution_sep2, 2, sampler1D, convolution_sep2, weights2)
201 SAMPLE_CONVOLUTION_SEP_N(sample_convolution_sep4, 4, sampler1D, convolution_sep4, weights4)
202 SAMPLE_CONVOLUTION_SEP_N(sample_convolution_sep6, 6, sampler2D, convolution_sep6, weights6)
203 SAMPLE_CONVOLUTION_SEP_N(sample_convolution_sep8, 8, sampler2D, convolution_sep8, weights8)
204 SAMPLE_CONVOLUTION_SEP_N(sample_convolution_sep12, 12, sampler2D, convolution_sep12, weights12)
205 SAMPLE_CONVOLUTION_SEP_N(sample_convolution_sep16, 16, sampler2D, convolution_sep16, weights16)
208 #define CONVOLUTION_N(NAME, N)                                               \
209     vec4 NAME(sampler2D tex, vec2 texcoord, vec2 pt, float taps_x[N],        \
210               float taps_y[N]) {                                             \
211         vec4 res = vec4(0);                                                  \
212         for (int y = 0; y < N; y++) {                                        \
213             vec4 line = vec4(0);                                             \
214             for (int x = 0; x < N; x++)                                      \
215                 line += taps_x[x] * texture(tex, texcoord + pt * vec2(x, y));\
216             res += taps_y[y] * line;                                         \
217         }                                                                    \
218         return res;                                                          \
219     }
221 CONVOLUTION_N(convolution2, 2)
222 CONVOLUTION_N(convolution4, 4)
223 CONVOLUTION_N(convolution6, 6)
224 CONVOLUTION_N(convolution8, 8)
225 CONVOLUTION_N(convolution12, 12)
226 CONVOLUTION_N(convolution16, 16)
228 #define SAMPLE_CONVOLUTION_N(NAME, N, SAMPLERT, CONV_FUNC, WEIGHTS_FUNC)    \
229     vec4 NAME(SAMPLERT lookup, sampler2D tex, vec2 texcoord) {              \
230         vec2 texsize = textureSize(tex, 0);                                 \
231         vec2 pt = 1 / texsize;                                              \
232         vec2 fcoord = fract(texcoord * texsize - 0.5);                      \
233         vec2 base = texcoord - fcoord * pt;                                 \
234         return CONV_FUNC(tex, base - pt * (N / 2 - 1), pt,                  \
235                          WEIGHTS_FUNC(lookup, fcoord.x),                    \
236                          WEIGHTS_FUNC(lookup, fcoord.y));                   \
237     }
239 SAMPLE_CONVOLUTION_N(sample_convolution2, 2, sampler1D, convolution2, weights2)
240 SAMPLE_CONVOLUTION_N(sample_convolution4, 4, sampler1D, convolution4, weights4)
241 SAMPLE_CONVOLUTION_N(sample_convolution6, 6, sampler2D, convolution6, weights6)
242 SAMPLE_CONVOLUTION_N(sample_convolution8, 8, sampler2D, convolution8, weights8)
243 SAMPLE_CONVOLUTION_N(sample_convolution12, 12, sampler2D, convolution12, weights12)
244 SAMPLE_CONVOLUTION_N(sample_convolution16, 16, sampler2D, convolution16, weights16)
247 // Unsharp masking
248 vec4 sample_sharpen3(sampler2D tex, vec2 texcoord) {
249     vec2 texsize = textureSize(tex, 0);
250     vec2 pt = 1 / texsize;
251     vec2 st = pt * 0.5;
252     vec4 p = texture(tex, texcoord);
253     vec4 sum = texture(tex, texcoord + st * vec2(+1, +1))
254              + texture(tex, texcoord + st * vec2(+1, -1))
255              + texture(tex, texcoord + st * vec2(-1, +1))
256              + texture(tex, texcoord + st * vec2(-1, -1));
257     return p + (p - 0.25 * sum) * filter_param1;
260 vec4 sample_sharpen5(sampler2D tex, vec2 texcoord) {
261     vec2 texsize = textureSize(tex, 0);
262     vec2 pt = 1 / texsize;
263     vec2 st1 = pt * 1.2;
264     vec4 p = texture(tex, texcoord);
265     vec4 sum1 = texture(tex, texcoord + st1 * vec2(+1, +1))
266               + texture(tex, texcoord + st1 * vec2(+1, -1))
267               + texture(tex, texcoord + st1 * vec2(-1, +1))
268               + texture(tex, texcoord + st1 * vec2(-1, -1));
269     vec2 st2 = pt * 1.5;
270     vec4 sum2 = texture(tex, texcoord + st2 * vec2(+1,  0))
271               + texture(tex, texcoord + st2 * vec2( 0, +1))
272               + texture(tex, texcoord + st2 * vec2(-1,  0))
273               + texture(tex, texcoord + st2 * vec2( 0, -1));
274     vec4 t = p * 0.859375 + sum2 * -0.1171875 + sum1 * -0.09765625;
275     return p + t * filter_param1;
278 void main() {
279 #ifdef USE_PLANAR
280     vec3 color = vec3(SAMPLE_L(texture1, texcoord).r,
281                       SAMPLE_C(texture2, texcoord).r,
282                       SAMPLE_C(texture3, texcoord).r);
283 #else
284     vec3 color = SAMPLE_L(texture1, texcoord).rgb;
285 #endif
286 #ifdef USE_GBRP
287     color.gbr = color;
288 #endif
289 #ifdef USE_YGRAY
290     // NOTE: actually slightly wrong for 16 bit input video, and completely
291     //       wrong for 9/10 bit input
292     color.gb = vec2(128.0/255.0);
293 #endif
294 #ifdef USE_COLORMATRIX
295     color = mat3(colormatrix) * color + colormatrix[3];
296 #endif
297 #ifdef USE_LINEAR_CONV
298     color = pow(color, vec3(2.2));
299 #endif
300 #ifdef USE_LINEAR_CONV_INV
301     // Convert from linear RGB to gamma RGB before putting it through the 3D-LUT
302     // in the final stage.
303     color = pow(color, vec3(1.0/2.2));
304 #endif
305 #ifdef USE_GAMMA_POW
306     color = pow(color, inv_gamma);
307 #endif
308 #ifdef USE_3DLUT
309     color = texture(lut_3d, color).rgb;
310 #endif
311 #ifdef USE_DITHER
312     float dither = texture(dither, gl_FragCoord.xy / textureSize(dither, 0)).r;
313     color = floor(color * dither_multiply + dither ) / dither_quantization;
314 #endif
315     out_color = vec4(color, 1);