]> git.sesse.net Git - casparcg/blob - core/mixer/image/image_shader.cpp
6d89630c2c2da0a54a550ac7b2537109d1c1d3ca
[casparcg] / core / mixer / image / image_shader.cpp
1 #include "../../StdAfx.h"\r
2 \r
3 #include "image_shader.h"\r
4 \r
5 #include "../gpu/shader.h"\r
6 #include "../gpu/ogl_device.h"\r
7 \r
8 #include "blending_glsl.h"\r
9 \r
10 #include <common/gl/gl_check.h>\r
11 #include <common/env.h>\r
12 \r
13 #include <tbb/mutex.h>\r
14 \r
15 namespace caspar { namespace core {\r
16 \r
17 std::shared_ptr<shader> g_shader;\r
18 tbb::mutex                              g_shader_mutex;\r
19 bool                                    g_blend_modes = false;\r
20 \r
21 std::string get_blend_color_func()\r
22 {\r
23         return \r
24                         \r
25         get_adjustement_glsl()\r
26                 \r
27         +\r
28 \r
29         get_blend_glsl()\r
30                 \r
31         +\r
32                         \r
33         "vec3 get_blend_color(vec3 back, vec3 fore)                                                                                     \n"\r
34         "{                                                                                                                                                                      \n"\r
35         "       switch(blend_mode)                                                                                                                              \n"\r
36         "       {                                                                                                                                                               \n"\r
37         "       case  0: return BlendNormal(back, fore);                                                                                \n"\r
38         "       case  1: return BlendLighten(back, fore);                                                                               \n"\r
39         "       case  2: return BlendDarken(back, fore);                                                                                \n"\r
40         "       case  3: return BlendMultiply(back, fore);                                                                              \n"\r
41         "       case  4: return BlendAverage(back, fore);                                                                               \n"\r
42         "       case  5: return BlendAdd(back, fore);                                                                                   \n"\r
43         "       case  6: return BlendSubstract(back, fore);                                                                             \n"\r
44         "       case  7: return BlendDifference(back, fore);                                                                    \n"\r
45         "       case  8: return BlendNegation(back, fore);                                                                              \n"\r
46         "       case  9: return BlendExclusion(back, fore);                                                                             \n"\r
47         "       case 10: return BlendScreen(back, fore);                                                                                \n"\r
48         "       case 11: return BlendOverlay(back, fore);                                                                               \n"\r
49         //"     case 12: return BlendSoftLight(back, fore);                                                                             \n"\r
50         "       case 13: return BlendHardLight(back, fore);                                                                             \n"\r
51         "       case 14: return BlendColorDodge(back, fore);                                                                    \n"\r
52         "       case 15: return BlendColorBurn(back, fore);                                                                             \n"\r
53         "       case 16: return BlendLinearDodge(back, fore);                                                                   \n"\r
54         "       case 17: return BlendLinearBurn(back, fore);                                                                    \n"\r
55         "       case 18: return BlendLinearLight(back, fore);                                                                   \n"\r
56         "       case 19: return BlendVividLight(back, fore);                                                                    \n"\r
57         "       case 20: return BlendPinLight(back, fore);                                                                              \n"\r
58         "       case 21: return BlendHardMix(back, fore);                                                                               \n"\r
59         "       case 22: return BlendReflect(back, fore);                                                                               \n"\r
60         "       case 23: return BlendGlow(back, fore);                                                                                  \n"\r
61         "       case 24: return BlendPhoenix(back, fore);                                                                               \n"\r
62         "       case 25: return BlendHue(back, fore);                                                                                   \n"\r
63         "       case 26: return BlendSaturation(back, fore);                                                                    \n"\r
64         "       case 27: return BlendColor(back, fore);                                                                                 \n"\r
65         "       case 28: return BlendLuminosity(back, fore);                                                                    \n"\r
66         "       }                                                                                                                                                               \n"\r
67         "       return BlendNormal(back, fore);                                                                                                 \n"\r
68         "}                                                                                                                                                                      \n"\r
69         "                                                                                                                                                                       \n"                                                                                                                                                       \r
70         "vec4 blend(vec4 fore)                                                                                                                          \n"\r
71         "{                                                                                                                                                                      \n"\r
72         "   vec4 back = texture2D(background, gl_TexCoord[1].st).bgra;                                          \n"             \r
73         "       fore.rgb = get_blend_color(back.rgb, fore.rgb);                                                                 \n"\r
74         "                                                                                                                                                                       \n"             \r
75         "       switch(keyer)                                                                                                                                   \n"\r
76         "       {                                                                                                                                                               \n"\r
77         "               case 0: return fore + (1.0-fore.a)*back; // linear                                                      \n"\r
78         "               case 1: return fore + back; // additive                                                                         \n"\r
79         "       }                                                                                                                                                               \n"\r
80         "                                                                                                                                                                       \n"                                     \r
81         "       return fore + (1.0-fore.a)*back;                                                                                                \n"\r
82         "}                                                                                                                                                                      \n";                    \r
83 }\r
84                 \r
85 std::string get_simple_blend_color_func()\r
86 {\r
87         return  \r
88                 \r
89         get_adjustement_glsl()\r
90                         \r
91         +\r
92 \r
93         "vec4 blend(vec4 fore)                                                                                                                          \n"\r
94         "{                                                                                                                                                                      \n"\r
95         "       return fore;                                                                                                                                    \n"\r
96         "}                                                                                                                                                                      \n";\r
97 }\r
98 \r
99 std::string get_vertex()\r
100 {\r
101         return \r
102 \r
103         "void main()                                                                                                                                            \n"\r
104         "{                                                                                                                                                                      \n"\r
105         "       gl_TexCoord[0] = gl_MultiTexCoord0;                                                                                             \n"\r
106         "       gl_TexCoord[1] = gl_MultiTexCoord1;                                                                                             \n"\r
107         "       gl_Position    = ftransform();                                                                                                  \n"\r
108         "}                                                                                                                                                                      \n";\r
109 }\r
110 \r
111 std::string get_fragment(bool blend_modes)\r
112 {\r
113         return\r
114 \r
115         "#version 120                                                                                                                                           \n"\r
116         "uniform sampler2D      background;                                                                                                             \n"\r
117         "uniform sampler2D      plane[4];                                                                                                               \n"\r
118         "uniform sampler2D      local_key;                                                                                                              \n"\r
119         "uniform sampler2D      layer_key;                                                                                                              \n"\r
120         "                                                                                                                                                                       \n"\r
121         "uniform bool           is_hd;                                                                                                                  \n"\r
122         "uniform bool           has_local_key;                                                                                                  \n"\r
123         "uniform bool           has_layer_key;                                                                                                  \n"\r
124         "uniform int            blend_mode;                                                                                                             \n"\r
125         "uniform int            keyer;                                                                                                                  \n"\r
126         "uniform int            pixel_format;                                                                                                   \n"\r
127         "                                                                                                                                                                       \n"\r
128         "uniform float          opacity;                                                                                                                \n"\r
129         "uniform bool           levels;                                                                                                                 \n"\r
130         "uniform float          min_input;                                                                                                              \n"\r
131         "uniform float          max_input;                                                                                                              \n"\r
132         "uniform float          gamma;                                                                                                                  \n"\r
133         "uniform float          min_output;                                                                                                             \n"\r
134         "uniform float          max_output;                                                                                                             \n"\r
135         "                                                                                                                                                                       \n"\r
136         "uniform bool           csb;                                                                                                                    \n"\r
137         "uniform float          brt;                                                                                                                    \n"\r
138         "uniform float          sat;                                                                                                                    \n"\r
139         "uniform float          con;                                                                                                                    \n"\r
140         "                                                                                                                                                                       \n"     \r
141 \r
142         +\r
143                 \r
144         (blend_modes ? get_blend_color_func() : get_simple_blend_color_func())\r
145 \r
146         +\r
147         \r
148         "                                                                                                                                                                       \n"\r
149         "//http://slouken.blogspot.com/2011/02/mpeg-acceleration-with-glsl.html                         \n"\r
150         "vec4 ycbcra_to_rgba_sd(float y, float cb, float cr, float a)                                           \n"\r
151         "{                                                                                                                                                                      \n"\r
152         "       // YUV offset                                                                                                                                   \n"\r
153         "       const vec3 offset = vec3(-0.0625, -0.5, -0.5);                                                                  \n"\r
154         "                                                                                                                                                                       \n"\r
155         "       // RGB coefficients                                                                                                                     \n"\r
156         "       const vec3 Rcoeff = vec3(1.164,  0.000,  1.596);                                                                \n"\r
157         "       const vec3 Gcoeff = vec3(1.164, -0.391, -0.813);                                                                \n"\r
158         "       const vec3 Bcoeff = vec3(1.164,  2.018,  0.000);                                                                \n"\r
159         "                                                                                                                                                                       \n"\r
160         "       vec3 yuv = vec3(y, cr, cb);                                                                                                             \n"\r
161         "   vec4 rgba;                                                                                                                                          \n"\r
162         "                                                                                                                                                                       \n"\r
163         "       yuv += offset;                                                                                                                                  \n"\r
164         "       rgba.r = dot(yuv, Rcoeff);                                                                                                              \n"\r
165         "       rgba.g = dot(yuv, Gcoeff);                                                                                                              \n"\r
166         "       rgba.b = dot(yuv, Bcoeff);                                                                                                              \n"\r
167         "       rgba.a = a;                                                                                                                                             \n"\r
168         "                                                                                                                                                                       \n"\r
169         "       return rgba;                                                                                                                                    \n"\r
170         "}                                                                                                                                                                      \n"                     \r
171         "                                                                                                                                                                       \n"\r
172         "vec4 ycbcra_to_rgba_hd(float y, float cb, float cr, float a)                                           \n"\r
173         "{                                                                                                                                                                      \n"\r
174         "       // YUV offset                                                                                                                                   \n"\r
175         "       const vec3 offset = vec3(-0.0625, -0.5, -0.5);                                                                  \n"\r
176         "                                                                                                                                                                       \n"\r
177         "       // RGB coefficients                                                                                                                     \n"\r
178         "       const vec3 Rcoeff = vec3(1.164,  0.000,  1.793);                                                                \n"\r
179         "       const vec3 Gcoeff = vec3(1.164, -0.213, -0.534);                                                                \n"\r
180         "       const vec3 Bcoeff = vec3(1.164,  2.115,  0.000);                                                                \n"\r
181         "                                                                                                                                                                       \n"\r
182         "       vec3 yuv = vec3(y, cr, cb);                                                                                                             \n"\r
183         "   vec4 rgba;                                                                                                                                          \n"\r
184         "                                                                                                                                                                       \n"\r
185         "       yuv += offset;                                                                                                                                  \n"\r
186         "       rgba.r = dot(yuv, Rcoeff);                                                                                                              \n"\r
187         "       rgba.g = dot(yuv, Gcoeff);                                                                                                              \n"\r
188         "       rgba.b = dot(yuv, Bcoeff);                                                                                                              \n"\r
189         "       rgba.a = a;                                                                                                                                             \n"\r
190         "                                                                                                                                                                       \n"\r
191         "       return rgba;                                                                                                                                    \n"\r
192         "}                                                                                                                                                                      \n"                     \r
193         "                                                                                                                                                                       \n"             \r
194         "vec4 ycbcra_to_rgba(float y, float cb, float cr, float a)                                                      \n"\r
195         "{                                                                                                                                                                      \n"\r
196         "       if(is_hd)                                                                                                                                               \n"\r
197         "               return ycbcra_to_rgba_hd(y, cb, cr, a);                                                                         \n"\r
198         "       else                                                                                                                                                    \n"\r
199         "               return ycbcra_to_rgba_sd(y, cb, cr, a);                                                                         \n"\r
200         "}                                                                                                                                                                      \n"\r
201         "                                                                                                                                                                       \n"\r
202         "vec4 get_rgba_color()                                                                                                                          \n"\r
203         "{                                                                                                                                                                      \n"\r
204         "       switch(pixel_format)                                                                                                                    \n"\r
205         "       {                                                                                                                                                               \n"\r
206         "       case 0:         //gray                                                                                                                          \n"\r
207         "               return vec4(texture2D(plane[0], gl_TexCoord[0].st).rrr, 1.0);                           \n"\r
208         "       case 1:         //bgra,                                                                                                                         \n"\r
209         "               return texture2D(plane[0], gl_TexCoord[0].st).bgra;                                                     \n"\r
210         "       case 2:         //rgba,                                                                                                                         \n"\r
211         "               return texture2D(plane[0], gl_TexCoord[0].st).rgba;                                                     \n"\r
212         "       case 3:         //argb,                                                                                                                         \n"\r
213         "               return texture2D(plane[0], gl_TexCoord[0].st).argb;                                                     \n"\r
214         "       case 4:         //abgr,                                                                                                                         \n"\r
215         "               return texture2D(plane[0], gl_TexCoord[0].st).gbar;                                                     \n"\r
216         "       case 5:         //ycbcr,                                                                                                                        \n"\r
217         "               {                                                                                                                                                       \n"\r
218         "                       float y  = texture2D(plane[0], gl_TexCoord[0].st).r;                                    \n"\r
219         "                       float cb = texture2D(plane[1], gl_TexCoord[0].st).r;                                    \n"\r
220         "                       float cr = texture2D(plane[2], gl_TexCoord[0].st).r;                                    \n"\r
221         "                       return ycbcra_to_rgba(y, cb, cr, 1.0);                                                                  \n"\r
222         "               }                                                                                                                                                       \n"\r
223         "       case 6:         //ycbcra                                                                                                                        \n"\r
224         "               {                                                                                                                                                       \n"\r
225         "                       float y  = texture2D(plane[0], gl_TexCoord[0].st).r;                                    \n"\r
226         "                       float cb = texture2D(plane[1], gl_TexCoord[0].st).r;                                    \n"\r
227         "                       float cr = texture2D(plane[2], gl_TexCoord[0].st).r;                                    \n"\r
228         "                       float a  = texture2D(plane[3], gl_TexCoord[0].st).r;                                    \n"\r
229         "                       return ycbcra_to_rgba(y, cb, cr, a);                                                                    \n"\r
230         "               }                                                                                                                                                       \n"\r
231         "       case 7:         //luma                                                                                                                          \n"\r
232         "               {                                                                                                                                                       \n"\r
233         "                       vec3 y3 = texture2D(plane[0], gl_TexCoord[0].st).rrr;                                   \n"\r
234         "                       return vec4((y3-0.065)/0.859, 1.0);                                                                             \n"\r
235         "               }                                                                                                                                                       \n"\r
236         "       }                                                                                                                                                               \n"\r
237         "       return vec4(0.0, 0.0, 0.0, 0.0);                                                                                                \n"\r
238         "}                                                                                                                                                                      \n"\r
239         "                                                                                                                                                                       \n"\r
240         "void main()                                                                                                                                            \n"\r
241         "{                                                                                                                                                                      \n"\r
242         "       vec4 color = get_rgba_color();                                                                                                  \n"\r
243         "   if(levels)                                                                                                                                          \n"\r
244         "               color.rgb = LevelsControl(color.rgb, min_input, max_input, gamma, min_output, max_output); \n"\r
245         "       if(csb)                                                                                                                                                 \n"\r
246         "               color.rgb = ContrastSaturationBrightness(color.rgb, brt, sat, con);                     \n"\r
247         "       if(has_local_key)                                                                                                                               \n"\r
248         "               color *= texture2D(local_key, gl_TexCoord[1].st).r;                                                     \n"\r
249         "       if(has_layer_key)                                                                                                                               \n"\r
250         "               color *= texture2D(layer_key, gl_TexCoord[1].st).r;                                                     \n"\r
251         "       color *= opacity;                                                                                                                               \n"\r
252         "       color = blend(color);                                                                                                                   \n"\r
253         "       gl_FragColor = color.bgra;                                                                                                              \n"\r
254         "}                                                                                                                                                                      \n";\r
255 }\r
256 \r
257 safe_ptr<shader> get_image_shader(ogl_device& ogl, bool& blend_modes)\r
258 {\r
259         tbb::mutex::scoped_lock lock(g_shader_mutex);\r
260 \r
261         if(g_shader)\r
262         {\r
263                 blend_modes = g_blend_modes;\r
264                 return make_safe(g_shader);\r
265         }\r
266                 \r
267         try\r
268         {                               \r
269                 g_blend_modes  = glTextureBarrierNV ? env::properties().get("configuration.mixers.blend-modes", false) : false;\r
270                 g_shader.reset(new shader(get_vertex(), get_fragment(g_blend_modes)));\r
271         }\r
272         catch(...)\r
273         {\r
274                 CASPAR_LOG_CURRENT_EXCEPTION();\r
275                 CASPAR_LOG(warning) << "Failed to compile shader. Trying to compile without blend-modes.";\r
276                                 \r
277                 g_blend_modes = false;\r
278                 g_shader.reset(new shader(get_vertex(), get_fragment(g_blend_modes)));\r
279         }\r
280                                                 \r
281         ogl.enable(GL_TEXTURE_2D);\r
282 \r
283         if(!g_blend_modes)\r
284         {\r
285                 ogl.enable(GL_BLEND);\r
286                 glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);\r
287                 CASPAR_LOG(info) << L"[shader] Blend-modes are disabled.";\r
288         }\r
289 \r
290         blend_modes = g_blend_modes;\r
291         return make_safe(g_shader);\r
292 }\r
293 \r
294 }}