]> git.sesse.net Git - casparcg/blob - core/mixer/image/shader/image_shader.cpp
Fixed serious bug with MIXER LEVELS
[casparcg] / core / mixer / image / shader / image_shader.cpp
1 /*\r
2 * Copyright 2013 Sveriges Television AB http://casparcg.com/\r
3 *\r
4 * This file is part of CasparCG (www.casparcg.com).\r
5 *\r
6 * CasparCG is free software: you can redistribute it and/or modify\r
7 * it under the terms of the GNU General Public License as published by\r
8 * the Free Software Foundation, either version 3 of the License, or\r
9 * (at your option) any later version.\r
10 *\r
11 * CasparCG is distributed in the hope that it will be useful,\r
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14 * GNU General Public License for more details.\r
15 *\r
16 * You should have received a copy of the GNU General Public License\r
17 * along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
18 *\r
19 * Author: Robert Nagy, ronag89@gmail.com\r
20 */\r
21 \r
22 #include "../../../StdAfx.h"\r
23 \r
24 #include "image_shader.h"\r
25 \r
26 #include "../../gpu/shader.h"\r
27 #include "../../gpu/ogl_device.h"\r
28 \r
29 #include "blending_glsl.h"\r
30 \r
31 #include <common/gl/gl_check.h>\r
32 #include <common/env.h>\r
33 \r
34 #include <tbb/mutex.h>\r
35 \r
36 namespace caspar { namespace core {\r
37 \r
38 std::shared_ptr<shader> g_shader;\r
39 tbb::mutex                              g_shader_mutex;\r
40 bool                                    g_blend_modes = false;\r
41 bool                                    g_post_processing = false;\r
42 \r
43 std::string get_blend_color_func()\r
44 {\r
45         return \r
46                         \r
47         get_adjustement_glsl()\r
48                 \r
49         +\r
50 \r
51         get_blend_glsl()\r
52                 \r
53         +\r
54                         \r
55         "vec3 get_blend_color(vec3 back, vec3 fore)                                                                                     \n"\r
56         "{                                                                                                                                                                      \n"\r
57         "       switch(blend_mode)                                                                                                                              \n"\r
58         "       {                                                                                                                                                               \n"\r
59         "       case  0: return BlendNormal(back, fore);                                                                                \n"\r
60         "       case  1: return BlendLighten(back, fore);                                                                               \n"\r
61         "       case  2: return BlendDarken(back, fore);                                                                                \n"\r
62         "       case  3: return BlendMultiply(back, fore);                                                                              \n"\r
63         "       case  4: return BlendAverage(back, fore);                                                                               \n"\r
64         "       case  5: return BlendAdd(back, fore);                                                                                   \n"\r
65         "       case  6: return BlendSubstract(back, fore);                                                                             \n"\r
66         "       case  7: return BlendDifference(back, fore);                                                                    \n"\r
67         "       case  8: return BlendNegation(back, fore);                                                                              \n"\r
68         "       case  9: return BlendExclusion(back, fore);                                                                             \n"\r
69         "       case 10: return BlendScreen(back, fore);                                                                                \n"\r
70         "       case 11: return BlendOverlay(back, fore);                                                                               \n"\r
71         //"     case 12: return BlendSoftLight(back, fore);                                                                             \n"\r
72         "       case 13: return BlendHardLight(back, fore);                                                                             \n"\r
73         "       case 14: return BlendColorDodge(back, fore);                                                                    \n"\r
74         "       case 15: return BlendColorBurn(back, fore);                                                                             \n"\r
75         "       case 16: return BlendLinearDodge(back, fore);                                                                   \n"\r
76         "       case 17: return BlendLinearBurn(back, fore);                                                                    \n"\r
77         "       case 18: return BlendLinearLight(back, fore);                                                                   \n"\r
78         "       case 19: return BlendVividLight(back, fore);                                                                    \n"\r
79         "       case 20: return BlendPinLight(back, fore);                                                                              \n"\r
80         "       case 21: return BlendHardMix(back, fore);                                                                               \n"\r
81         "       case 22: return BlendReflect(back, fore);                                                                               \n"\r
82         "       case 23: return BlendGlow(back, fore);                                                                                  \n"\r
83         "       case 24: return BlendPhoenix(back, fore);                                                                               \n"\r
84         "       case 25: return BlendHue(back, fore);                                                                                   \n"\r
85         "       case 26: return BlendSaturation(back, fore);                                                                    \n"\r
86         "       case 27: return BlendColor(back, fore);                                                                                 \n"\r
87         "       case 28: return BlendLuminosity(back, fore);                                                                    \n"\r
88         "       }                                                                                                                                                               \n"\r
89         "       return BlendNormal(back, fore);                                                                                                 \n"\r
90         "}                                                                                                                                                                      \n"\r
91         "                                                                                                                                                                       \n"                                                                                                                                                       \r
92         "vec4 blend(vec4 fore)                                                                                                                          \n"\r
93         "{                                                                                                                                                                      \n"\r
94         "   vec4 back = texture2D(background, gl_TexCoord[1].st).bgra;                                          \n"\r
95         "   if(blend_mode != 0)                                                                                                                         \n"\r
96         "               fore.rgb = get_blend_color(back.rgb/(back.a+0.0000001), fore.rgb/(fore.a+0.0000001))*fore.a;\n"\r
97         "       switch(keyer)                                                                                                                                   \n"     \r
98         "       {                                                                                                                                                               \n"     \r
99         "               case 1:  return fore + back; // additive                                                                        \n"\r
100         "               default: return fore + (1.0-fore.a)*back; // linear                                                     \n"\r
101         "       }                                                                                                                                                               \n"\r
102         "}                                                                                                                                                                      \n";                    \r
103 }\r
104                 \r
105 std::string get_simple_blend_color_func()\r
106 {\r
107         return  \r
108                 \r
109         get_adjustement_glsl()\r
110                         \r
111         +\r
112 \r
113         "vec4 blend(vec4 fore)                                                                                                                          \n"\r
114         "{                                                                                                                                                                      \n"\r
115         "       return fore;                                                                                                                                    \n"\r
116         "}                                                                                                                                                                      \n";\r
117 }\r
118 \r
119 std::string get_vertex()\r
120 {\r
121         return \r
122 \r
123         "void main()                                                                                                                                            \n"\r
124         "{                                                                                                                                                                      \n"\r
125         "       gl_TexCoord[0] = gl_MultiTexCoord0;                                                                                             \n"\r
126         "       gl_TexCoord[1] = gl_MultiTexCoord1;                                                                                             \n"\r
127         "       gl_Position    = ftransform();                                                                                                  \n"\r
128         "}                                                                                                                                                                      \n";\r
129 }\r
130 \r
131 std::string get_chroma_func()\r
132 {\r
133         return get_chroma_glsl()\r
134 \r
135         +\r
136 \r
137                 "vec4 chroma_key(vec4 c)                                                \n"\r
138                 "{                                                                      \n"\r
139                 "   switch (chroma_mode)                                                \n"\r
140                 "   {                                                                   \n"\r
141                 "   case 0: return c;                                                   \n"\r
142                 "   case 1: return ChromaOnGreen(c.bgra).bgra;                          \n"\r
143                 "   case 2: return ChromaOnBlue(c.bgra).bgra;                           \n"\r
144                 "   }                                                                   \n"\r
145                 "   return c;                                                           \n"\r
146                 "}                                                                      \n";\r
147 }\r
148 \r
149 std::string get_fragment(bool blend_modes, bool chroma_key, bool post_processing)\r
150 {\r
151         return\r
152 \r
153         "#version 130                                                                                                                                           \n"\r
154         "uniform sampler2D      background;                                                                                                             \n"\r
155         "uniform sampler2D      plane[4];                                                                                                               \n"\r
156         "uniform sampler2D      local_key;                                                                                                              \n"\r
157         "uniform sampler2D      layer_key;                                                                                                              \n"\r
158         "                                                                                                                                                                       \n"\r
159         "uniform bool           is_hd;                                                                                                                  \n"\r
160         "uniform bool           has_local_key;                                                                                                  \n"\r
161         "uniform bool           has_layer_key;                                                                                                  \n"\r
162         "uniform int            blend_mode;                                                                                                             \n"\r
163         "uniform int            keyer;                                                                                                                  \n"\r
164         "uniform int            pixel_format;                                                                                                   \n"\r
165         "                                                                                                                                                                       \n"\r
166         "uniform float          opacity;                                                                                                                \n"\r
167         "uniform bool           levels;                                                                                                                 \n"\r
168         "uniform float          min_input;                                                                                                              \n"\r
169         "uniform float          max_input;                                                                                                              \n"\r
170         "uniform float          gamma;                                                                                                                  \n"\r
171         "uniform float          min_output;                                                                                                             \n"\r
172         "uniform float          max_output;                                                                                                             \n"\r
173         "                                                                                                                                                                       \n"\r
174         "uniform bool           csb;                                                                                                                    \n"\r
175         "uniform float          brt;                                                                                                                    \n"\r
176         "uniform float          sat;                                                                                                                    \n"\r
177         "uniform float          con;                                                                                                                    \n"\r
178         "                                                                                                                                                                       \n"     \r
179         "uniform bool           post_processing;                                                                                                \n"\r
180         "uniform bool           straighten_alpha;                                                                                               \n"\r
181         "                                                                                                                                                                       \n"     \r
182     "uniform int        chroma_mode;                                                    \n"\r
183     "uniform vec2       chroma_blend;                                                   \n"\r
184     "uniform float      chroma_spill;                                                   \n"\r
185 \r
186         +\r
187                 \r
188         (blend_modes ? get_blend_color_func() : get_simple_blend_color_func())\r
189 \r
190 \r
191     +\r
192 \r
193     get_chroma_func()\r
194 \r
195         +\r
196         \r
197         "                                                                                                                                                                       \n"\r
198         "vec4 ycbcra_to_rgba_sd(float Y, float Cb, float Cr, float A)                                           \n"\r
199         "{                                                                                                                                                                      \n"\r
200         "   vec4 rgba;                                                                                                                                          \n"\r
201         "   rgba.b = (1.164*(Y*255 - 16) + 1.596*(Cr*255 - 128))/255;                                           \n"\r
202         "   rgba.g = (1.164*(Y*255 - 16) - 0.813*(Cr*255 - 128) - 0.391*(Cb*255 - 128))/255;\n"\r
203         "   rgba.r = (1.164*(Y*255 - 16) + 2.018*(Cb*255 - 128))/255;                                           \n"\r
204         "   rgba.a = A;                                                                                                                                         \n"\r
205         "       return rgba;                                                                                                                                    \n"     \r
206         "}                                                                                                                                                                      \n"                     \r
207         "                                                                                                                                                                       \n"\r
208         "vec4 ycbcra_to_rgba_hd(float Y, float Cb, float Cr, float A)                                           \n"\r
209         "{                                                                                                                                                                      \n"\r
210         "   vec4 rgba;                                                                                                                                          \n"\r
211         "   rgba.b = (1.164*(Y*255 - 16) + 1.793*(Cr*255 - 128))/255;                                           \n"\r
212         "   rgba.g = (1.164*(Y*255 - 16) - 0.534*(Cr*255 - 128) - 0.213*(Cb*255 - 128))/255;\n"\r
213         "   rgba.r = (1.164*(Y*255 - 16) + 2.115*(Cb*255 - 128))/255;                                           \n"\r
214         "   rgba.a = A;                                                                                                                                         \n"\r
215         "       return rgba;                                                                                                                                    \n"\r
216         "}                                                                                                                                                                      \n"                     \r
217         "                                                                                                                                                                       \n"             \r
218         "vec4 ycbcra_to_rgba(float y, float cb, float cr, float a)                                                      \n"\r
219         "{                                                                                                                                                                      \n"\r
220         "       if(is_hd)                                                                                                                                               \n"\r
221         "               return ycbcra_to_rgba_hd(y, cb, cr, a);                                                                         \n"\r
222         "       else                                                                                                                                                    \n"\r
223         "               return ycbcra_to_rgba_sd(y, cb, cr, a);                                                                         \n"\r
224         "}                                                                                                                                                                      \n"\r
225         "                                                                                                                                                                       \n"\r
226         "vec4 get_rgba_color()                                                                                                                          \n"\r
227         "{                                                                                                                                                                      \n"\r
228         "       switch(pixel_format)                                                                                                                    \n"\r
229         "       {                                                                                                                                                               \n"\r
230         "       case 0:         //gray                                                                                                                          \n"\r
231         "               return vec4(texture2D(plane[0], gl_TexCoord[0].st).rrr, 1.0);                           \n"\r
232         "       case 1:         //bgra,                                                                                                                         \n"\r
233         "               return texture2D(plane[0], gl_TexCoord[0].st).bgra;                                                     \n"\r
234         "       case 2:         //rgba,                                                                                                                         \n"\r
235         "               return texture2D(plane[0], gl_TexCoord[0].st).rgba;                                                     \n"\r
236         "       case 3:         //argb,                                                                                                                         \n"\r
237         "               return texture2D(plane[0], gl_TexCoord[0].st).argb;                                                     \n"\r
238         "       case 4:         //abgr,                                                                                                                         \n"\r
239         "               return texture2D(plane[0], gl_TexCoord[0].st).gbar;                                                     \n"\r
240         "       case 5:         //ycbcr,                                                                                                                        \n"\r
241         "               {                                                                                                                                                       \n"\r
242         "                       float y  = texture2D(plane[0], gl_TexCoord[0].st).r;                                    \n"\r
243         "                       float cb = texture2D(plane[1], gl_TexCoord[0].st).r;                                    \n"\r
244         "                       float cr = texture2D(plane[2], gl_TexCoord[0].st).r;                                    \n"\r
245         "                       return ycbcra_to_rgba(y, cb, cr, 1.0);                                                                  \n"\r
246         "               }                                                                                                                                                       \n"\r
247         "       case 6:         //ycbcra                                                                                                                        \n"\r
248         "               {                                                                                                                                                       \n"\r
249         "                       float y  = texture2D(plane[0], gl_TexCoord[0].st).r;                                    \n"\r
250         "                       float cb = texture2D(plane[1], gl_TexCoord[0].st).r;                                    \n"\r
251         "                       float cr = texture2D(plane[2], gl_TexCoord[0].st).r;                                    \n"\r
252         "                       float a  = texture2D(plane[3], gl_TexCoord[0].st).r;                                    \n"\r
253         "                       return ycbcra_to_rgba(y, cb, cr, a);                                                                    \n"\r
254         "               }                                                                                                                                                       \n"\r
255         "       case 7:         //luma                                                                                                                          \n"\r
256         "               {                                                                                                                                                       \n"\r
257         "                       vec3 y3 = texture2D(plane[0], gl_TexCoord[0].st).rrr;                                   \n"\r
258         "                       return vec4((y3-0.065)/0.859, 1.0);                                                                             \n"\r
259         "               }                                                                                                                                                       \n"\r
260         "       }                                                                                                                                                               \n"\r
261         "       return vec4(0.0, 0.0, 0.0, 0.0);                                                                                                \n"\r
262         "}                                                                                                                                                                      \n"\r
263         "                                                                                                                                                                       \n"\r
264         "vec4 post_process()                                                                                                                            \n"\r
265         "{                                                                                                                                                                      \n"\r
266         "       vec4 color = texture2D(background, gl_TexCoord[0].st).bgra;                                             \n"\r
267         "                                                                                                                                                                       \n"\r
268         "       if (straighten_alpha)                                                                                                                   \n"\r
269         "               color.rgb /= color.a + 0.0000001;                                                                                       \n"\r
270         "                                                                                                                                                                       \n"\r
271         "       return color;                                                                                                                                   \n"\r
272         "}                                                                                                                                                                      \n"\r
273         "                                                                                                                                                                       \n"\r
274         "void main()                                                                                                                                            \n"\r
275         "{                                                                                                                                                                      \n"\r
276         +\r
277         (post_processing ? \r
278         "       if (post_processing)                                                                                                                    \n"\r
279         "       {                                                                                                                                                               \n"\r
280         "               gl_FragColor = post_process().bgra;                                                                                     \n"\r
281         "       }                                                                                                                                                               \n"\r
282         "       else                                                                                                                                                    \n" : "")\r
283         +\r
284         "       {                                                                                                                                                               \n"\r
285         "               vec4 color = get_rgba_color();                                                                                          \n"\r
286         +\r
287         (chroma_key ? "         color = chroma_key(color);\n" : "")\r
288         +\r
289         "               if(levels)                                                                                                                                      \n"\r
290         "                       color.rgb = LevelsControl(                                                                                              \n"\r
291         "                                       color.rgb, min_input, gamma, max_input, min_output, max_output);\n"\r
292         "               if(csb)                                                                                                                                         \n"\r
293         "                       color.rgb = ContrastSaturationBrightness(color, brt, sat, con);                 \n"\r
294         "               if(has_local_key)                                                                                                                       \n"\r
295         "                       color *= texture2D(local_key, gl_TexCoord[1].st).r;                                             \n"\r
296         "               if(has_layer_key)                                                                                                                       \n"\r
297         "                       color *= texture2D(layer_key, gl_TexCoord[1].st).r;                                             \n"\r
298         "               color *= opacity;                                                                                                                       \n"\r
299         "               color = blend(color);                                                                                                           \n"\r
300         "               gl_FragColor = color.bgra;                                                                                                      \n"\r
301         "       }                                                                                                                                                               \n"\r
302         "}                                                                                                                                                                      \n";\r
303 }\r
304 \r
305 safe_ptr<shader> get_image_shader(\r
306                 ogl_device& ogl, bool& blend_modes, bool& post_processing)\r
307 {\r
308         tbb::mutex::scoped_lock lock(g_shader_mutex);\r
309 \r
310         if(g_shader)\r
311         {\r
312                 blend_modes = g_blend_modes;\r
313                 post_processing = g_post_processing;\r
314 \r
315                 return make_safe_ptr(g_shader);\r
316         }\r
317                 \r
318         bool chroma_key = env::properties().get(L"configuration.mixer.chroma-key", false);\r
319         bool straight_alpha = env::properties().get(L"configuration.mixer.straight-alpha", false);\r
320         g_post_processing = straight_alpha;\r
321 \r
322         try\r
323         {                               \r
324                 g_blend_modes  = glTextureBarrierNV ? env::properties().get(L"configuration.mixer.blend-modes", false) : false;\r
325                 g_shader.reset(new shader(get_vertex(), get_fragment(g_blend_modes, chroma_key, g_post_processing)));\r
326         }\r
327         catch(...)\r
328         {\r
329                 CASPAR_LOG_CURRENT_EXCEPTION();\r
330                 CASPAR_LOG(warning) << "Failed to compile shader. Trying to compile without blend-modes.";\r
331                                 \r
332                 g_blend_modes = false;\r
333                 g_shader.reset(new shader(get_vertex(), get_fragment(g_blend_modes, chroma_key, g_post_processing)));\r
334         }\r
335                                                 \r
336         ogl.enable(GL_TEXTURE_2D);\r
337 \r
338         if(!g_blend_modes)\r
339         {\r
340                 ogl.enable(GL_BLEND);\r
341                 glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);\r
342                 CASPAR_LOG(info) << L"[shader] Blend-modes are disabled.";\r
343         }\r
344 \r
345         blend_modes = g_blend_modes;\r
346         post_processing = g_post_processing;\r
347 \r
348         return make_safe_ptr(g_shader);\r
349 }\r
350 \r
351 }}\r