prevent popup deactivation while button_down
[goodguy/history.git] / cinelerra-5.0 / cinelerra / playback3d.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2009 Adam Williams <broadcast at earthling dot net>
5  * 
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * 
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  * 
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  * 
20  */
21
22 #define GL_GLEXT_PROTOTYPES
23
24 #include "bcsignals.h"
25 #include "bcwindowbase.h"
26 #include "canvas.h"
27 #include "clip.h"
28 #include "condition.h"
29 #include "maskautos.h"
30 #include "maskauto.h"
31 #include "mutex.h"
32 #include "overlayframe.inc"
33 #include "playback3d.h"
34 #include "pluginclient.h"
35 #include "pluginvclient.h"
36 #include "transportque.inc"
37 #include "vframe.h"
38
39 #ifdef HAVE_GL
40 #include <GL/gl.h>
41 #include <GL/glext.h>
42 #include <GL/glu.h>
43 #endif
44
45 #include <string.h>
46 #include <unistd.h>
47 #include <fcntl.h>
48
49
50
51 // Shaders
52 // These should be passed to VFrame::make_shader to construct shaders.
53 // Can't hard code sampler2D
54
55
56 static const char *yuv_to_rgb_frag = 
57         "uniform sampler2D tex;\n"
58         "void main()\n"
59         "{\n"
60         "       vec4 yuva = texture2D(tex, gl_TexCoord[0].st);\n"
61         "       yuva.rgb -= vec3(0, 0.5, 0.5);\n"
62         "       const mat3 yuv_to_rgb_matrix = mat3(\n"
63         "               1,       1,        1, \n"
64         "               0,       -0.34414, 1.77200, \n"
65         "               1.40200, -0.71414, 0);\n"
66         "       gl_FragColor = vec4(yuv_to_rgb_matrix * yuva.rgb, yuva.a);\n"
67         "}\n";
68
69 static const char *yuva_to_yuv_frag = 
70         "uniform sampler2D tex;\n"
71         "void main()\n"
72         "{\n"
73         "       vec4 yuva = texture2D(tex, gl_TexCoord[0].st);\n"
74         "       float a = yuva.a;\n"
75         "       float anti_a = 1.0 - a;\n"
76         "       yuva.r *= a;\n"
77         "       yuva.g = yuva.g * a + 0.5 * anti_a;\n"
78         "       yuva.b = yuva.b * a + 0.5 * anti_a;\n"
79         "       yuva.a = 1.0;\n"
80         "       gl_FragColor = yuva;\n"
81         "}\n";
82
83 static const char *yuva_to_rgb_frag = 
84         "uniform sampler2D tex;\n"
85         "void main()\n"
86         "{\n"
87         "       vec4 yuva = texture2D(tex, gl_TexCoord[0].st);\n"
88         "       yuva.rgb -= vec3(0, 0.5, 0.5);\n"
89         "       const mat3 yuv_to_rgb_matrix = mat3(\n"
90         "               1,       1,        1, \n"
91         "               0,       -0.34414, 1.77200, \n"
92         "               1.40200, -0.71414, 0);\n"
93         "       yuva.rgb = yuv_to_rgb_matrix * yuva.rgb;\n"
94         "       yuva.rgb *= yuva.a;\n"
95         "       yuva.a = 1.0;\n"
96         "       gl_FragColor = yuva;\n"
97         "}\n";
98
99 static const char *rgb_to_yuv_frag = 
100         "uniform sampler2D tex;\n"
101         "void main()\n"
102         "{\n"
103         "       vec4 rgba = texture2D(tex, gl_TexCoord[0].st);\n"
104         "       const mat3 rgb_to_yuv_matrix = mat3(\n"
105         "               0.29900, -0.16874, 0.50000, \n"
106         "               0.58700, -0.33126, -0.41869, \n"
107         "               0.11400, 0.50000,  -0.08131);\n"
108         "       rgba.rgb = rgb_to_yuv_matrix * rgba.rgb;\n"
109         "       rgba.rgb += vec3(0, 0.5, 0.5);\n"
110         "       gl_FragColor = rgba;\n"
111         "}\n";
112
113
114 static const char *rgba_to_rgb_frag = 
115         "uniform sampler2D tex;\n"
116         "void main()\n"
117         "{\n"
118         "       vec4 rgba = texture2D(tex, gl_TexCoord[0].st);\n"
119         "       rgba.rgb *= rgba.a;\n"
120         "       rgba.a = 1.0;\n"
121         "       gl_FragColor = rgba;\n"
122         "}\n";
123
124 static const char *rgba_to_yuv_frag = 
125         "uniform sampler2D tex;\n"
126         "void main()\n"
127         "{\n"
128         "       vec4 rgba = texture2D(tex, gl_TexCoord[0].st);\n"
129         "       const mat3 rgb_to_yuv_matrix = mat3(\n"
130         "               0.29900, -0.16874, 0.50000, \n"
131         "               0.58700, -0.33126, -0.41869, \n"
132         "               0.11400, 0.50000,  -0.08131);\n"
133         "       rgba.rgb *= rgba.a;\n"
134         "       rgba.a = 1.0;\n"
135         "       rgba.rgb = rgb_to_yuv_matrix * rgba.rgb;\n"
136         "       rgba.rgb += vec3(0, 0.5, 0.5);\n"
137         "       gl_FragColor = rgba;\n"
138         "}\n";
139
140 static const char *rgba_to_rgb_flatten = 
141         "void main() {\n"
142         "       gl_FragColor.rgb *= gl_FragColor.a;\n"
143         "       gl_FragColor.a = 1.0;\n"
144         "}\n";
145
146 // NORMAL
147 static const char *blend_normal_frag = 
148         "uniform sampler2D tex2;\n"
149         "uniform vec2 tex2_dimensions;\n"
150         "uniform float alpha;\n"
151         "void main() {\n"
152         "       gl_FragColor.a *= alpha;\n"
153         "       vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n"
154         "       vec4 result = canvas * (1.0 - gl_FragColor.a) + gl_FragColor * gl_FragColor.a;\n"
155         "       gl_FragColor = mix(canvas, result, alpha);\n"
156         "}\n";
157
158 // ADDITION
159 static const char *blend_add_frag = 
160         "uniform sampler2D tex2;\n"
161         "uniform vec2 tex2_dimensions;\n"
162         "uniform float alpha;\n"
163         "void main() {\n"
164         "       gl_FragColor.a *= alpha;\n"
165         "       vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n"
166         "       vec4 result = canvas + gl_FragColor;\n"
167         "       result = clamp(result, 0.0, 1.0);\n"
168         "       gl_FragColor = mix(canvas, result, alpha);\n"
169         "}\n";
170
171 // SUBTRACT
172 static const char *blend_subtract_frag = 
173         "uniform sampler2D tex2;\n"
174         "uniform vec2 tex2_dimensions;\n"
175         "uniform float alpha;\n"
176         "void main() {\n"
177         "       gl_FragColor.a *= alpha;\n"
178         "       vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n"
179         "       vec4 result = gl_FragColor - canvas;\n"
180         "       result = clamp(result, 0.0, 1.0);\n"
181         "       gl_FragColor = mix(canvas, result, alpha);\n"
182         "}\n";
183
184 // MULTIPLY
185 static const char *blend_multiply_frag = 
186         "uniform sampler2D tex2;\n"
187         "uniform vec2 tex2_dimensions;\n"
188         "uniform float alpha;\n"
189         "void main() {\n"
190         "       gl_FragColor.a *= alpha;\n"
191         "       vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n"
192         "       vec4 result = canvas * gl_FragColor;\n"
193         "       gl_FragColor = mix(canvas, result, alpha);\n"
194         "}\n";
195
196 // DIVIDE
197 static const char *blend_divide_frag = 
198         "uniform sampler2D tex2;\n"
199         "uniform vec2 tex2_dimensions;\n"
200         "uniform float alpha;\n"
201         "void main() {\n"
202         "       gl_FragColor.a *= alpha;\n"
203         "       vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n"
204         "       vec4 result = gl_FragColor / canvas;\n"
205         "       if(!canvas.r) result.r = 1.0;\n"
206         "       if(!canvas.g) result.g = 1.0;\n"
207         "       if(!canvas.b) result.b = 1.0;\n"
208         "       if(!canvas.a) result.a = 1.0;\n"
209         "       result = clamp(result, 0.0, 1.0);\n"
210         "       gl_FragColor = mix(canvas, result, alpha);\n"
211         "}\n";
212
213 // REPLACE
214 static const char *blend_replace_frag = 
215         "uniform float alpha;\n"
216         "void main() {\n"
217         "       gl_FragColor.a *= alpha;\n"
218         "}\n";
219
220 // MAX
221 static const char *blend_max_frag = 
222         "uniform sampler2D tex2;\n"
223         "uniform vec2 tex2_dimensions;\n"
224         "uniform float alpha;\n"
225         "void main() {\n"
226         "       gl_FragColor.a *= alpha;\n"
227         "       vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n"
228         "       vec4 result = max(canvas, gl_FragColor);\n"
229         "       result = clamp(result, 0.0, 1.0);\n"
230         "       gl_FragColor = mix(canvas, result, alpha);\n"
231         "}\n";
232
233 // MIN
234 static const char *blend_min_frag = 
235         "uniform sampler2D tex2;\n"
236         "uniform vec2 tex2_dimensions;\n"
237         "uniform float alpha;\n"
238         "void main() {\n"
239         "       gl_FragColor.a *= alpha;\n"
240         "       vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n"
241         "       vec4 result = min(canvas, gl_FragColor);\n"
242         "       result = clamp(result, 0.0, 1.0);\n"
243         "       gl_FragColor = mix(canvas, result, alpha);\n"
244         "}\n";
245
246 // AVERAGE
247 static const char *blend_average_frag = 
248         "uniform sampler2D tex2;\n"
249         "uniform vec2 tex2_dimensions;\n"
250         "uniform float alpha;\n"
251         "void main() {\n"
252         "       gl_FragColor.a *= alpha;\n"
253         "       vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n"
254         "       vec4 result = (canvas + gl_FragColor) * 0.5;\n"
255         "       result = clamp(result, 0.0, 1.0);\n"
256         "       gl_FragColor = mix(canvas, result, alpha);\n"
257         "}\n";
258
259 // DARKEN
260 static const char *blend_darken_frag =
261         "uniform sampler2D tex2;\n"
262         "uniform vec2 tex2_dimensions;\n"
263         "uniform float alpha;\n"
264         "void main() {\n"
265         "       gl_FragColor.a *= alpha;\n"
266         "       vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n"
267         "       vec4 result = vec4(canvas.rgb * (1.0 - gl_FragColor.a) +"
268                         " gl_FragColor.rgb * (1.0 - canvas.a) +"
269                         " min(canvas.rgb, gl_FragColor.rgb), "
270                         " canvas.a + gl_FragColor.a - canvas.a * gl_FragColor.a);\n"
271         "       result = clamp(result, 0.0, 1.0);\n"
272         "       gl_FragColor = mix(canvas, result, alpha);\n"
273         "}\n";
274
275 // LIGHTEN
276 static const char *blend_lighten_frag =
277         "uniform sampler2D tex2;\n"
278         "uniform vec2 tex2_dimensions;\n"
279         "uniform float alpha;\n"
280         "void main() {\n"
281         "       gl_FragColor.a *= alpha;\n"
282         "       vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n"
283         "       vec4 result = vec4(canvas.rgb * (1.0 - gl_FragColor.a) +"
284                         " gl_FragColor.rgb * (1.0 - canvas.a) +"
285                         " max(canvas.rgb, gl_FragColor.rgb), "
286                         " canvas.a + gl_FragColor.a - canvas.a * gl_FragColor.a);\n"
287         "       result = clamp(result, 0.0, 1.0);\n"
288         "       gl_FragColor = mix(canvas, result, alpha);\n"
289         "}\n";
290
291 // DST
292 static const char *blend_dst_frag =
293         "uniform sampler2D tex2;\n"
294         "uniform vec2 tex2_dimensions;\n"
295         "uniform float alpha;\n"
296         "void main() {\n"
297 //      "       gl_FragColor.a *= alpha;\n"
298 //      "       vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n"
299 //      "       vec4 result = canvas;\n"
300 //      "       gl_FragColor = mix(result, canvas, alpha);\n"
301         "       gl_FragColor = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n"
302         "}\n";
303
304 // DST_ATOP
305 static const char *blend_dst_atop_frag =
306         "uniform sampler2D tex2;\n"
307         "uniform vec2 tex2_dimensions;\n"
308         "uniform float alpha;\n"
309         "void main() {\n"
310         "       gl_FragColor.a *= alpha;\n"
311         "       vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n"
312         "       vec4 result = vec4(canvas.rgb * gl_FragColor.a + "
313                         "(1.0 - canvas.a) * gl_FragColor.rgb, gl_FragColor.a);\n"
314         "       gl_FragColor = mix(canvas, result, alpha);\n"
315         "}\n";
316
317 // DST_IN
318 static const char *blend_dst_in_frag =
319         "uniform sampler2D tex2;\n"
320         "uniform vec2 tex2_dimensions;\n"
321         "uniform float alpha;\n"
322         "void main() {\n"
323         "       gl_FragColor.a *= alpha;\n"
324         "       vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n"
325         "       vec4 result = canvas * gl_FragColor.a;\n"
326         "       gl_FragColor = mix(canvas, result, alpha);\n"
327         "}\n";
328
329 // DST_OUT
330 static const char *blend_dst_out_frag =
331         "uniform sampler2D tex2;\n"
332         "uniform vec2 tex2_dimensions;\n"
333         "uniform float alpha;\n"
334         "void main() {\n"
335         "       gl_FragColor.a *= alpha;\n"
336         "       vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n"
337         "       vec4 result = canvas * (1.0 - gl_FragColor.a);\n"
338         "       gl_FragColor = mix(canvas, result, alpha);\n"
339         "}\n";
340
341 // DST_OVER
342 static const char *blend_dst_over_frag =
343         "uniform sampler2D tex2;\n"
344         "uniform vec2 tex2_dimensions;\n"
345         "uniform float alpha;\n"
346         "void main() {\n"
347         "       gl_FragColor.a *= alpha;\n"
348         "       vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n"
349         "       vec4 result = vec4(canvas.rgb + (1.0 - canvas.a) * gl_FragColor.rgb, "
350                         " gl_FragColor.a + canvas.a - gl_FragColor.a * canvas.a);\n"
351         "       gl_FragColor = mix(canvas, result, alpha);\n"
352         "}\n";
353
354 // SRC
355 static const char *blend_src_frag =
356         "uniform sampler2D tex2;\n"
357         "uniform vec2 tex2_dimensions;\n"
358         "uniform float alpha;\n"
359         "void main() {\n"
360         "       gl_FragColor.a *= alpha;\n"
361         "       vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n"
362         "       vec4 result = gl_FragColor;\n"
363         "       gl_FragColor = mix(canvas, result, alpha);\n"
364         "}\n";
365
366 // SRC_ATOP
367 static const char *blend_src_atop_frag =
368         "uniform sampler2D tex2;\n"
369         "uniform vec2 tex2_dimensions;\n"
370         "uniform float alpha;\n"
371         "void main() {\n"
372         "       gl_FragColor.a *= alpha;\n"
373         "       vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n"
374         "       vec4 result = vec4(gl_FragColor.rgb * canvas.a + "
375                         "canvas.rgb * (1.0 - gl_FragColor.a), canvas.a);\n"
376         "       gl_FragColor = mix(canvas, result, alpha);\n"
377         "}\n";
378
379 // SRC_IN 
380 static const char *blend_src_in_frag =
381         "uniform sampler2D tex2;\n"
382         "uniform vec2 tex2_dimensions;\n"
383         "uniform float alpha;\n"
384         "void main() {\n"
385         "       gl_FragColor.a *= alpha;\n"
386         "       vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n"
387         "       vec4 result = gl_FragColor * canvas.a;\n"
388         "       gl_FragColor = mix(canvas, result, alpha);\n"
389         "}\n";
390
391 // SRC_OUT
392 static const char *blend_src_out_frag =
393         "uniform sampler2D tex2;\n"
394         "uniform vec2 tex2_dimensions;\n"
395         "uniform float alpha;\n"
396         "void main() {\n"
397         "       gl_FragColor.a *= alpha;\n"
398         "       vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n"
399         "       vec4 result = gl_FragColor * (1.0 - canvas.a);\n"
400         "       gl_FragColor = mix(canvas, result, alpha);\n"
401         "}\n";
402
403 // SRC_OVER
404 static const char *blend_src_over_frag =
405         "uniform sampler2D tex2;\n"
406         "uniform vec2 tex2_dimensions;\n"
407         "uniform float alpha;\n"
408         "void main() {\n"
409         "       gl_FragColor.a *= alpha;\n"
410         "       vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n"
411         "       vec4 result = vec4(gl_FragColor.rgb + (1.0 - gl_FragColor.a) * canvas.rgb, "
412                                 "gl_FragColor.a + canvas.a - gl_FragColor.a * canvas.a);\n"
413         "       gl_FragColor = mix(canvas, result, alpha);\n"
414         "}\n";
415
416 // OR
417 static const char *blend_or_frag = 
418         "uniform sampler2D tex2;\n"
419         "uniform vec2 tex2_dimensions;\n"
420         "uniform float alpha;\n"
421         "void main() {\n"
422         "       gl_FragColor.a *= alpha;\n"
423         "       vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n"
424         "       vec4 result = canvas + gl_FragColor - canvas * gl_FragColor;\n"
425         "       result = clamp(result, 0.0, 1.0);\n"
426         "       gl_FragColor = mix(canvas, result, alpha);\n"
427         "}\n";
428
429 // XOR
430 static const char *blend_xor_frag =
431         "uniform sampler2D tex2;\n"
432         "uniform vec2 tex2_dimensions;\n"
433         "uniform float alpha;\n"
434         "void main() {\n"
435         "       gl_FragColor.a *= alpha;\n"
436         "       vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n"
437         "       vec4 result = vec4(gl_FragColor.rgb * (1.0 - canvas.a) + "
438                         "(1.0 - gl_FragColor.a) * canvas.rgb, "
439                         "gl_FragColor.a + canvas.a - 2.0 * gl_FragColor.a * canvas.a);\n"
440         "       gl_FragColor = mix(canvas, result, alpha);\n"
441         "}\n";
442
443 static const char *read_texture_frag = 
444         "uniform sampler2D tex;\n"
445         "void main()\n"
446         "{\n"
447         "       gl_FragColor = texture2D(tex, gl_TexCoord[0].st);\n"
448         "}\n";
449
450 static const char *multiply_mask4_frag = 
451         "uniform sampler2D tex;\n"
452         "uniform sampler2D tex1;\n"
453         "uniform float scale;\n"
454         "void main()\n"
455         "{\n"
456         "       gl_FragColor = texture2D(tex, gl_TexCoord[0].st);\n"
457         "       gl_FragColor.a *= texture2D(tex1, gl_TexCoord[0].st / vec2(scale, scale)).r;\n"
458         "}\n";
459
460 static const char *multiply_mask3_frag = 
461         "uniform sampler2D tex;\n"
462         "uniform sampler2D tex1;\n"
463         "uniform float scale;\n"
464         "uniform bool is_yuv;\n"
465         "void main()\n"
466         "{\n"
467         "       gl_FragColor = texture2D(tex, gl_TexCoord[0].st);\n"
468         "       float a = texture2D(tex1, gl_TexCoord[0].st / vec2(scale, scale)).r;\n"
469         "       gl_FragColor.rgb *= vec3(a, a, a);\n"
470         "}\n";
471
472 static const char *multiply_yuvmask3_frag = 
473         "uniform sampler2D tex;\n"
474         "uniform sampler2D tex1;\n"
475         "uniform float scale;\n"
476         "void main()\n"
477         "{\n"
478         "       gl_FragColor = texture2D(tex, gl_TexCoord[0].st);\n"
479         "       float a = texture2D(tex1, gl_TexCoord[0].st / vec2(scale, scale)).r;\n"
480         "       gl_FragColor.gb -= vec2(0.5, 0.5);\n"
481         "       gl_FragColor.rgb *= vec3(a, a, a);\n"
482         "       gl_FragColor.gb += vec2(0.5, 0.5);\n"
483         "}\n";
484
485 static const char *fade_rgba_frag =
486         "uniform sampler2D tex;\n"
487         "uniform float alpha;\n"
488         "void main()\n"
489         "{\n"
490         "       gl_FragColor = texture2D(tex, gl_TexCoord[0].st);\n"
491         "       gl_FragColor.a *= alpha;\n"
492         "}\n";
493
494 static const char *fade_yuv_frag =
495         "uniform sampler2D tex;\n"
496         "uniform float alpha;\n"
497         "void main()\n"
498         "{\n"
499         "       gl_FragColor = texture2D(tex, gl_TexCoord[0].st);\n"
500         "       gl_FragColor.r *= alpha;\n"
501         "       gl_FragColor.gb -= vec2(0.5, 0.5);\n"
502         "       gl_FragColor.g *= alpha;\n"
503         "       gl_FragColor.b *= alpha;\n"
504         "       gl_FragColor.gb += vec2(0.5, 0.5);\n"
505         "}\n";
506
507
508
509
510
511
512
513
514 Playback3DCommand::Playback3DCommand()
515  : BC_SynchronousCommand()
516 {
517         canvas = 0;
518         is_nested = 0;
519 }
520
521 void Playback3DCommand::copy_from(BC_SynchronousCommand *command)
522 {
523         Playback3DCommand *ptr = (Playback3DCommand*)command;
524         this->canvas = ptr->canvas;
525         this->is_cleared = ptr->is_cleared;
526
527         this->in_x1 = ptr->in_x1;
528         this->in_y1 = ptr->in_y1;
529         this->in_x2 = ptr->in_x2;
530         this->in_y2 = ptr->in_y2;
531         this->out_x1 = ptr->out_x1;
532         this->out_y1 = ptr->out_y1;
533         this->out_x2 = ptr->out_x2;
534         this->out_y2 = ptr->out_y2;
535         this->alpha = ptr->alpha;
536         this->mode = ptr->mode;
537         this->interpolation_type = ptr->interpolation_type;
538
539         this->input = ptr->input;
540         this->start_position_project = ptr->start_position_project;
541         this->keyframe_set = ptr->keyframe_set;
542         this->keyframe = ptr->keyframe;
543         this->default_auto = ptr->default_auto;
544         this->plugin_client = ptr->plugin_client;
545         this->want_texture = ptr->want_texture;
546         this->is_nested = ptr->is_nested;
547         this->dst_cmodel = ptr->dst_cmodel;
548
549         BC_SynchronousCommand::copy_from(command);
550 }
551
552
553 ///static void glDebugCallback(GLenum src, GLenum typ, GLuint id,
554 ///     GLenum svy, GLsizei len, const GLchar* msg, void* dat)
555 //static void glDebugCallback(unsigned int src, unsigned int typ, unsigned int id,
556 //      unsigned int svy, int len, const char* msg, const void* dat)
557 //{
558 //      printf("glDebug: %d:%d; %d/%d %s\n",src,typ,id,svy,msg);
559 //}
560
561
562 Playback3D::Playback3D(MWindow *mwindow)
563  : BC_Synchronous()
564 {
565         this->mwindow = mwindow;
566         temp_texture = 0;
567         //Enabling OpenGL debug output on nVidia drivers
568 //      glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, 0, GL_TRUE);
569 //      glEnable(GL_DEBUG_OUTPUT);
570 //      glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
571 //      glDebugMessageCallback(glDebugCallback, 0);
572 }
573
574 Playback3D::~Playback3D()
575 {
576 }
577
578
579
580
581 BC_SynchronousCommand* Playback3D::new_command()
582 {
583         return new Playback3DCommand;
584 }
585
586
587
588 void Playback3D::handle_command(BC_SynchronousCommand *command)
589 {
590 //printf("Playback3D::handle_command 1 %d\n", command->command);
591         switch(command->command)
592         {
593                 case Playback3DCommand::WRITE_BUFFER:
594                         write_buffer_sync((Playback3DCommand*)command);
595                         break;
596
597                 case Playback3DCommand::CLEAR_OUTPUT:
598                         clear_output_sync((Playback3DCommand*)command);
599                         break;
600
601                 case Playback3DCommand::CLEAR_INPUT:
602                         clear_input_sync((Playback3DCommand*)command);
603                         break;
604
605                 case Playback3DCommand::DO_CAMERA:
606                         do_camera_sync((Playback3DCommand*)command);
607                         break;
608
609                 case Playback3DCommand::OVERLAY:
610                         overlay_sync((Playback3DCommand*)command);
611                         break;
612
613                 case Playback3DCommand::DO_FADE:
614                         do_fade_sync((Playback3DCommand*)command);
615                         break;
616
617                 case Playback3DCommand::DO_MASK:
618                         do_mask_sync((Playback3DCommand*)command);
619                         break;
620
621                 case Playback3DCommand::PLUGIN:
622                         run_plugin_sync((Playback3DCommand*)command);
623                         break;
624
625                 case Playback3DCommand::COPY_FROM:
626                         copy_from_sync((Playback3DCommand*)command);
627                         break;
628
629                 case Playback3DCommand::CONVERT_CMODEL:
630                         convert_cmodel_sync((Playback3DCommand*)command);
631                         break;
632
633 //              case Playback3DCommand::DRAW_REFRESH:
634 //                      draw_refresh_sync((Playback3DCommand*)command);
635 //                      break;
636         }
637 //printf("Playback3D::handle_command 10\n");
638 }
639
640
641
642
643 void Playback3D::copy_from(Canvas *canvas, 
644         VFrame *dst,
645         VFrame *src,
646         int want_texture)
647 {
648         Playback3DCommand command;
649         command.command = Playback3DCommand::COPY_FROM;
650         command.canvas = canvas;
651         command.frame = dst;
652         command.input = src;
653         command.want_texture = want_texture;
654         send_command(&command);
655 }
656
657 void Playback3D::copy_from_sync(Playback3DCommand *command)
658 {
659 #ifdef HAVE_GL
660         command->canvas->lock_canvas("Playback3D::draw_refresh_sync");
661         BC_WindowBase *window = command->canvas->get_canvas();
662         if(window)
663         {
664                 window->lock_window("Playback3D:draw_refresh_sync");
665                 window->enable_opengl();
666                 int w = command->input->get_w();
667                 int h = command->input->get_h();
668
669                 if(command->input->get_opengl_state() == VFrame::SCREEN &&
670                         w == command->frame->get_w() && h == command->frame->get_h())
671                 {
672 // printf("Playback3D::copy_from_sync 1 %d %d %d %d %d\n", 
673 // command->input->get_w(),
674 // command->input->get_h(),
675 // command->frame->get_w(),
676 // command->frame->get_h(),
677 // command->frame->get_color_model());
678 // With NVidia at least,
679                         if(w % 4)
680                         {
681                                 printf("Playback3D::copy_from_sync: w=%d not supported because it is not divisible by 4.\n", w);
682                         }
683                         else
684 // Copy to texture
685                         if(command->want_texture)
686                         {
687 //printf("Playback3D::copy_from_sync 1 dst=%p src=%p\n", command->frame, command->input);
688 // Screen_to_texture requires the source pbuffer enabled.
689                                 command->input->enable_opengl();
690                                 command->frame->screen_to_texture();
691                                 command->frame->set_opengl_state(VFrame::TEXTURE);
692                         }
693                         else
694 // Copy to RAM
695                         {
696                                 command->input->enable_opengl();
697                                 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
698                                 glReadPixels(0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE,
699                                         command->frame->get_rows()[0]);
700                                 command->frame->flip_vert();
701                                 command->frame->set_opengl_state(VFrame::RAM);
702                         }
703                 }
704                 else
705                 {
706                         printf("Playback3D::copy_from_sync: invalid formats opengl_state=%d %dx%d -> %dx%d\n",
707                                 command->input->get_opengl_state(), w, h,
708                                 command->frame->get_w(), command->frame->get_h());
709                 }
710
711                 window->unlock_window();
712         }
713         command->canvas->unlock_canvas();
714 #endif
715 }
716
717
718
719
720 // void Playback3D::draw_refresh(Canvas *canvas, 
721 //      VFrame *frame,
722 //      float in_x1, 
723 //      float in_y1, 
724 //      float in_x2, 
725 //      float in_y2, 
726 //      float out_x1, 
727 //      float out_y1, 
728 //      float out_x2, 
729 //      float out_y2)
730 // {
731 //      Playback3DCommand command;
732 //      command.command = Playback3DCommand::DRAW_REFRESH;
733 //      command.canvas = canvas;
734 //      command.frame = frame;
735 //      command.in_x1 = in_x1;
736 //      command.in_y1 = in_y1;
737 //      command.in_x2 = in_x2;
738 //      command.in_y2 = in_y2;
739 //      command.out_x1 = out_x1;
740 //      command.out_y1 = out_y1;
741 //      command.out_x2 = out_x2;
742 //      command.out_y2 = out_y2;
743 //      send_command(&command);
744 // }
745 // 
746 // void Playback3D::draw_refresh_sync(Playback3DCommand *command)
747 // {
748 //      command->canvas->lock_canvas("Playback3D::draw_refresh_sync");
749 //      BC_WindowBase *window = command->canvas->get_canvas();
750 //      if(window)
751 //      {
752 //              window->lock_window("Playback3D:draw_refresh_sync");
753 //              window->enable_opengl();
754 // 
755 // // Read output pbuffer back to RAM in project colormodel
756 // // RGB 8bit is fastest for OpenGL to read back.
757 //              command->frame->reallocate(0, 
758 //                      0,
759 //                      0,
760 //                      0,
761 //                      command->frame->get_w(), 
762 //                      command->frame->get_h(), 
763 //                      BC_RGB888, 
764 //                      -1);
765 //              command->frame->to_ram();
766 // 
767 //              window->clear_box(0, 
768 //                                              0, 
769 //                                              window->get_w(), 
770 //                                              window->get_h());
771 //              window->draw_vframe(command->frame,
772 //                                                      (int)command->out_x1, 
773 //                                                      (int)command->out_y1, 
774 //                                                      (int)(command->out_x2 - command->out_x1), 
775 //                                                      (int)(command->out_y2 - command->out_y1),
776 //                                                      (int)command->in_x1, 
777 //                                                      (int)command->in_y1, 
778 //                                                      (int)(command->in_x2 - command->in_x1), 
779 //                                                      (int)(command->in_y2 - command->in_y1),
780 //                                                      0);
781 // 
782 //              window->unlock_window();
783 //      }
784 //      command->canvas->unlock_canvas();
785 // }
786
787
788
789
790
791 void Playback3D::write_buffer(Canvas *canvas, 
792         VFrame *frame,
793         float in_x1, 
794         float in_y1, 
795         float in_x2, 
796         float in_y2, 
797         float out_x1, 
798         float out_y1, 
799         float out_x2, 
800         float out_y2, 
801         int is_cleared)
802 {
803         Playback3DCommand command;
804         command.command = Playback3DCommand::WRITE_BUFFER;
805         command.canvas = canvas;
806         command.frame = frame;
807         command.in_x1 = in_x1;
808         command.in_y1 = in_y1;
809         command.in_x2 = in_x2;
810         command.in_y2 = in_y2;
811         command.out_x1 = out_x1;
812         command.out_y1 = out_y1;
813         command.out_x2 = out_x2;
814         command.out_y2 = out_y2;
815         command.is_cleared = is_cleared;
816         send_command(&command);
817 }
818
819
820 void Playback3D::write_buffer_sync(Playback3DCommand *command)
821 {
822         command->canvas->lock_canvas("Playback3D::write_buffer_sync");
823         if(command->canvas->get_canvas())
824         {
825                 BC_WindowBase *window = command->canvas->get_canvas();
826                 window->lock_window("Playback3D::write_buffer_sync");
827 // Update hidden cursor
828                 window->update_video_cursor();
829 // Make sure OpenGL is enabled first.
830                 window->enable_opengl();
831
832
833 //printf("Playback3D::write_buffer_sync 1 %d\n", window->get_id());
834                 switch(command->frame->get_opengl_state())
835                 {
836 // Upload texture and composite to screen
837                         case VFrame::RAM:
838                                 command->frame->to_texture();
839                                 draw_output(command);
840                                 break;
841 // Composite texture to screen and swap buffer
842                         case VFrame::TEXTURE:
843                                 draw_output(command);
844                                 break;
845                         case VFrame::SCREEN:
846 // swap buffers only
847                                 window->flip_opengl();
848                                 break;
849                         default:
850                                 printf("Playback3D::write_buffer_sync unknown state\n");
851                                 break;
852                 }
853                 window->unlock_window();
854         }
855
856         command->canvas->unlock_canvas();
857 }
858
859
860
861 void Playback3D::draw_output(Playback3DCommand *command)
862 {
863 #ifdef HAVE_GL
864         int texture_id = command->frame->get_texture_id();
865         BC_WindowBase *window = command->canvas->get_canvas();
866
867 // printf("Playback3D::draw_output 1 texture_id=%d window=%p\n", 
868 // texture_id,
869 // command->canvas->get_canvas());
870
871
872
873
874 // If virtual console is being used, everything in this function has
875 // already been done except the page flip.
876         if(texture_id >= 0)
877         {
878                 canvas_w = window->get_w();
879                 canvas_h = window->get_h();
880                 VFrame::init_screen(canvas_w, canvas_h);
881
882                 if(!command->is_cleared)
883                 {
884 // If we get here, the virtual console was not used.
885                         init_frame(command);
886                 }
887
888 // Texture
889 // Undo any previous shader settings
890                 command->frame->bind_texture(0);
891
892
893
894
895 // Convert colormodel
896                 unsigned int frag_shader = 0;
897                 switch(command->frame->get_color_model())
898                 {
899                         case BC_YUV888:
900                         case BC_YUVA8888:
901                                 frag_shader = VFrame::make_shader(0,
902                                         yuv_to_rgb_frag,
903                                         0);
904                                 break;
905                 }
906
907
908                 if(frag_shader > 0) 
909                 {
910                         glUseProgram(frag_shader);
911                         int variable = glGetUniformLocation(frag_shader, "tex");
912 // Set texture unit of the texture
913                         glUniform1i(variable, 0);
914                 }
915
916                 if(BC_CModels::components(command->frame->get_color_model()) == 4)
917                 {
918                         glEnable(GL_BLEND);
919                         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
920                 }
921
922                 command->frame->draw_texture(
923                         command->in_x1, command->in_y1, command->in_x2, command->in_y2,
924                         command->out_x1, command->out_y1, command->out_x2, command->out_y2,
925                         1);
926
927
928 // printf("Playback3D::draw_output 2 %f,%f %f,%f -> %f,%f %f,%f\n",
929 // command->in_x1,
930 // command->in_y1,
931 // command->in_x2,
932 // command->in_y2,
933 // command->out_x1,
934 // command->out_y1,
935 // command->out_x2,
936 // command->out_y2);
937
938                 glUseProgram(0);
939
940                 command->canvas->get_canvas()->flip_opengl();
941                 
942         }
943 #endif
944 }
945
946
947 void Playback3D::init_frame(Playback3DCommand *command)
948 {
949 #ifdef HAVE_GL
950         canvas_w = command->canvas->get_canvas()->get_w();
951         canvas_h = command->canvas->get_canvas()->get_h();
952
953         glClearColor(0.0, 0.0, 0.0, 0.0);
954         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
955 #endif
956 }
957
958
959 void Playback3D::clear_output(Canvas *canvas, VFrame *output)
960 {
961         Playback3DCommand command;
962         command.command = Playback3DCommand::CLEAR_OUTPUT;
963         command.canvas = canvas;
964         command.frame = output;
965         send_command(&command);
966 }
967
968 void Playback3D::clear_output_sync(Playback3DCommand *command)
969 {
970         command->canvas->lock_canvas("Playback3D::clear_output_sync");
971         if(command->canvas->get_canvas())
972         {
973                 command->canvas->get_canvas()->lock_window("Playback3D::clear_output_sync");
974 // If we get here, the virtual console is being used.
975                 command->canvas->get_canvas()->enable_opengl();
976
977 // Using pbuffer for refresh frame.
978                 if(command->frame)
979                 {
980                         command->frame->enable_opengl();
981                 }       
982
983
984                 init_frame(command);
985                 command->canvas->get_canvas()->unlock_window();
986         }
987         command->canvas->unlock_canvas();
988 }
989
990
991 void Playback3D::clear_input(Canvas *canvas, VFrame *frame)
992 {
993         Playback3DCommand command;
994         command.command = Playback3DCommand::CLEAR_INPUT;
995         command.canvas = canvas;
996         command.frame = frame;
997         send_command(&command);
998 }
999
1000 void Playback3D::clear_input_sync(Playback3DCommand *command)
1001 {
1002         command->canvas->lock_canvas("Playback3D::clear_output_sync");
1003         if(command->canvas->get_canvas())
1004         {
1005                 command->canvas->get_canvas()->lock_window("Playback3D::clear_output_sync");
1006                 command->canvas->get_canvas()->enable_opengl();
1007                 command->frame->enable_opengl();
1008                 command->frame->clear_pbuffer();
1009                 command->frame->set_opengl_state(VFrame::SCREEN);
1010                 command->canvas->get_canvas()->unlock_window();
1011         }
1012         command->canvas->unlock_canvas();
1013 }
1014
1015 void Playback3D::do_camera(Canvas *canvas,
1016         VFrame *output,
1017         VFrame *input,
1018         float in_x1, 
1019         float in_y1, 
1020         float in_x2, 
1021         float in_y2, 
1022         float out_x1, 
1023         float out_y1, 
1024         float out_x2, 
1025         float out_y2)
1026 {
1027         Playback3DCommand command;
1028         command.command = Playback3DCommand::DO_CAMERA;
1029         command.canvas = canvas;
1030         command.input = input;
1031         command.frame = output;
1032         command.in_x1 = in_x1;
1033         command.in_y1 = in_y1;
1034         command.in_x2 = in_x2;
1035         command.in_y2 = in_y2;
1036         command.out_x1 = out_x1;
1037         command.out_y1 = out_y1;
1038         command.out_x2 = out_x2;
1039         command.out_y2 = out_y2;
1040         send_command(&command);
1041 }
1042
1043 void Playback3D::do_camera_sync(Playback3DCommand *command)
1044 {
1045         command->canvas->lock_canvas("Playback3D::do_camera_sync");
1046         if(command->canvas->get_canvas())
1047         {
1048                 command->canvas->get_canvas()->lock_window("Playback3D::clear_output_sync");
1049                 command->canvas->get_canvas()->enable_opengl();
1050
1051                 command->input->to_texture();
1052                 command->frame->enable_opengl();
1053                 command->frame->init_screen();
1054                 command->frame->clear_pbuffer();
1055
1056                 command->input->bind_texture(0);
1057 // Must call draw_texture in input frame to get the texture coordinates right.
1058
1059 // printf("Playback3D::do_camera_sync 1 %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f\n", 
1060 // command->in_x1, 
1061 // command->in_y2, 
1062 // command->in_x2, 
1063 // command->in_y1, 
1064 // command->out_x1,
1065 // (float)command->input->get_h() - command->out_y1,
1066 // command->out_x2,
1067 // (float)command->input->get_h() - command->out_y2);
1068                 command->input->draw_texture(
1069                         command->in_x1, command->in_y2, 
1070                         command->in_x2, command->in_y1, 
1071                         command->out_x1,
1072                         (float)command->frame->get_h() - command->out_y1,
1073                         command->out_x2,
1074                         (float)command->frame->get_h() - command->out_y2);
1075
1076
1077                 command->frame->set_opengl_state(VFrame::SCREEN);
1078                 command->canvas->get_canvas()->unlock_window();
1079         }
1080         command->canvas->unlock_canvas();
1081 }
1082
1083 void Playback3D::overlay(Canvas *canvas, VFrame *input, 
1084         float in_x1, float in_y1, float in_x2, float in_y2, 
1085         float out_x1, float out_y1, float out_x2, float out_y2, 
1086         float alpha, int mode, int interpolation_type,
1087         VFrame *output, int is_nested)
1088 {
1089         Playback3DCommand command;
1090         command.command = Playback3DCommand::OVERLAY;
1091         command.canvas = canvas;
1092         command.frame = output;
1093         command.input = input;
1094         command.in_x1 = in_x1;
1095         command.in_y1 = in_y1;
1096         command.in_x2 = in_x2;
1097         command.in_y2 = in_y2;
1098         command.out_x1 = out_x1;
1099         command.out_y1 = out_y1;
1100         command.out_x2 = out_x2;
1101         command.out_y2 = out_y2;
1102         command.alpha = alpha;
1103         command.mode = mode;
1104         command.interpolation_type = interpolation_type;
1105         command.is_nested = is_nested;
1106         send_command(&command);
1107 }
1108
1109 void Playback3D::overlay_sync(Playback3DCommand *command)
1110 {
1111 #ifdef HAVE_GL
1112 // To do these operations, we need to copy the input buffer to a texture
1113 // and blend 2 textures in a shader
1114         static const char * const overlay_shaders[TRANSFER_TYPES] = {
1115                 blend_normal_frag,      // TRANSFER_NORMAL
1116                 blend_add_frag,         // TRANSFER_ADDITION
1117                 blend_subtract_frag,    // TRANSFER_SUBTRACT
1118                 blend_multiply_frag,    // TRANSFER_MULTIPLY
1119                 blend_divide_frag,      // TRANSFER_DIVIDE
1120                 blend_replace_frag,     // TRANSFER_REPLACE
1121                 blend_max_frag,         // TRANSFER_MAX
1122                 blend_min_frag,         // TRANSFER_MIN
1123                 blend_average_frag,     // TRANSFER_AVERAGE
1124                 blend_darken_frag,      // TRANSFER_DARKEN
1125                 blend_lighten_frag,     // TRANSFER_LIGHTEN
1126                 blend_dst_frag,         // TRANSFER_DST
1127                 blend_dst_atop_frag,    // TRANSFER_DST_ATOP
1128                 blend_dst_in_frag,      // TRANSFER_DST_IN
1129                 blend_dst_out_frag,     // TRANSFER_DST_OUT
1130                 blend_dst_over_frag,    // TRANSFER_DST_OVER
1131                 blend_src_frag,         // TRANSFER_SRC
1132                 blend_src_atop_frag,    // TRANSFER_SRC_ATOP
1133                 blend_src_in_frag,      // TRANSFER_SRC_IN
1134                 blend_src_out_frag,     // TRANSFER_SRC_OUT
1135                 blend_src_over_frag,    // TRANSFER_SRC_OVER
1136                 blend_or_frag,          // TRANSFER_OR
1137                 blend_xor_frag          // TRANSFER_XOR
1138         };
1139
1140         command->canvas->lock_canvas("Playback3D::overlay_sync");
1141         if(command->canvas->get_canvas()) {
1142                 BC_WindowBase *window = command->canvas->get_canvas();
1143                 window->lock_window("Playback3D::overlay_sync");
1144 // Make sure OpenGL is enabled first.
1145                 window->enable_opengl();
1146                 window->update_video_cursor();
1147
1148                 glColor4f(1, 1, 1, 1);
1149                 glDisable(GL_BLEND);
1150
1151                 if(command->frame) {
1152 // Render to PBuffer
1153                         command->frame->enable_opengl();
1154                         command->frame->set_opengl_state(VFrame::SCREEN);
1155                         canvas_w = command->frame->get_w();
1156                         canvas_h = command->frame->get_h();
1157                 }
1158                 else {
1159 // Render to canvas
1160                         canvas_w = window->get_w();
1161                         canvas_h = window->get_h();
1162                 }
1163
1164
1165 //printf("Playback3D::overlay_sync 1 %d\n", command->input->get_opengl_state());
1166                 switch(command->input->get_opengl_state()) {
1167 // Upload texture and composite to screen
1168                 case VFrame::RAM:
1169                         command->input->to_texture();
1170                         break;
1171 // Just composite texture to screen
1172                 case VFrame::TEXTURE:
1173                         break;
1174 // read from PBuffer to texture, then composite texture to screen
1175                 case VFrame::SCREEN:
1176                         command->input->enable_opengl();
1177                         command->input->screen_to_texture();
1178                         if(command->frame)
1179                                 command->frame->enable_opengl();
1180                         else
1181                                 window->enable_opengl();
1182                         break;
1183                 default:
1184                         printf("Playback3D::overlay_sync unknown state\n");
1185                         break;
1186                 }
1187
1188
1189                 const char *shader_stack[4] = { 0, 0, 0, 0, };
1190                 int total_shaders = 0;
1191
1192                 VFrame::init_screen(canvas_w, canvas_h);
1193
1194 // Enable texture
1195                 command->input->bind_texture(0);
1196
1197 // Convert colormodel to RGB if not nested.
1198 // The color model setting in the output frame is ignored.
1199                 if( command->is_nested <= 0 ) {  // not nested
1200                         switch(command->input->get_color_model()) {
1201                         case BC_YUV888:
1202                         case BC_YUVA8888:
1203                                 shader_stack[total_shaders++] = yuv_to_rgb_frag;
1204                                 break;
1205                         }
1206                 }
1207
1208 // get the shaders
1209 #define add_shader(s) \
1210   if(!total_shaders) shader_stack[total_shaders++] = read_texture_frag; \
1211   shader_stack[total_shaders++] = s
1212
1213                 switch(command->mode) {
1214                 case TRANSFER_REPLACE:
1215 // This requires overlaying an alpha multiplied image on a black screen.
1216                         if( command->input->get_texture_components() != 4 ) break;
1217                         add_shader(overlay_shaders[command->mode]);
1218                         break;
1219                 default:
1220                         enable_overlay_texture(command);
1221                         add_shader(overlay_shaders[command->mode]);
1222                         break;
1223                 }
1224
1225 // if to flatten alpha
1226                 if( command->is_nested < 0 ) {
1227                         switch(command->input->get_color_model()) {
1228 // yuv has already been converted to rgb
1229                         case BC_YUVA8888:
1230                         case BC_RGBA_FLOAT:
1231                         case BC_RGBA8888:
1232                                 add_shader(rgba_to_rgb_flatten);
1233                                 break;
1234                         }
1235                 }
1236
1237 // run the shaders
1238                 unsigned int frag_shader = 0;
1239                 if(shader_stack[0]) {
1240                         frag_shader = VFrame::make_shader(0,
1241                                 shader_stack[0], shader_stack[1],
1242                                 shader_stack[2], shader_stack[3], 0);
1243
1244                         glUseProgram(frag_shader);
1245
1246 // Set texture unit of the texture
1247                         glUniform1i(glGetUniformLocation(frag_shader, "tex"), 0);
1248 // Set texture unit of the temp texture
1249                         glUniform1i(glGetUniformLocation(frag_shader, "tex2"), 1);
1250 // Set alpha
1251                         int variable = glGetUniformLocation(frag_shader, "alpha");
1252                         glUniform1f(variable, command->alpha);
1253 // Set dimensions of the temp texture
1254                         if(temp_texture)
1255                                 glUniform2f(glGetUniformLocation(frag_shader, "tex2_dimensions"), 
1256                                         (float)temp_texture->get_texture_w(), 
1257                                         (float)temp_texture->get_texture_h());
1258                 }
1259                 else
1260                         glUseProgram(0);
1261
1262
1263 // printf("Playback3D::overlay_sync %f %f %f %f %f %f %f %f\n",
1264 // command->in_x1, command->in_y1, command->in_x2, command->in_y2,
1265 // command->out_x1, command->out_y1, command->out_x2, command->out_y2);
1266
1267                 command->input->draw_texture(
1268                         command->in_x1, command->in_y1, command->in_x2, command->in_y2,
1269                         command->out_x1, command->out_y1, command->out_x2, command->out_y2,
1270 // Don't flip vertical if nested
1271                         command->is_nested > 0 ? 0 : 1);
1272                 glUseProgram(0);
1273
1274 // Delete temp texture
1275                 if(temp_texture) {
1276                         delete temp_texture;
1277                         temp_texture = 0;
1278                         glActiveTexture(GL_TEXTURE1);
1279                         glDisable(GL_TEXTURE_2D);
1280                 }
1281                 glActiveTexture(GL_TEXTURE0);
1282                 glDisable(GL_TEXTURE_2D);
1283
1284                 window->unlock_window();
1285         }
1286         command->canvas->unlock_canvas();
1287 #endif
1288 }
1289
1290 void Playback3D::enable_overlay_texture(Playback3DCommand *command)
1291 {
1292 #ifdef HAVE_GL
1293         glDisable(GL_BLEND);
1294
1295         glActiveTexture(GL_TEXTURE1);
1296         BC_Texture::new_texture(&temp_texture, canvas_w, canvas_h, 
1297                 command->input->get_color_model());
1298         temp_texture->bind(1);
1299
1300 // Read canvas into texture
1301         glReadBuffer(GL_BACK);
1302         glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, canvas_w, canvas_h);
1303 #endif
1304 }
1305
1306
1307 void Playback3D::do_mask(Canvas *canvas,
1308         VFrame *output, 
1309         int64_t start_position_project,
1310         MaskAutos *keyframe_set, 
1311         MaskAuto *keyframe,
1312         MaskAuto *default_auto)
1313 {
1314         Playback3DCommand command;
1315         command.command = Playback3DCommand::DO_MASK;
1316         command.canvas = canvas;
1317         command.frame = output;
1318         command.start_position_project = start_position_project;
1319         command.keyframe_set = keyframe_set;
1320         command.keyframe = keyframe;
1321         command.default_auto = default_auto;
1322
1323         send_command(&command);
1324 }
1325
1326
1327
1328 #ifdef HAVE_GL
1329 static void combine_callback(GLdouble coords[3], 
1330         GLdouble *vertex_data[4],
1331         GLfloat weight[4], 
1332         GLdouble **dataOut)
1333 {
1334         GLdouble *vertex;
1335
1336         vertex = (GLdouble *) malloc(6 * sizeof(GLdouble));
1337         vertex[0] = coords[0];
1338         vertex[1] = coords[1];
1339         vertex[2] = coords[2];
1340
1341         for (int i = 3; i < 6; i++)
1342         {
1343                 vertex[i] = weight[0] * vertex_data[0][i] +
1344                         weight[1] * vertex_data[1][i] +
1345                         weight[2] * vertex_data[2][i] +
1346                         weight[3] * vertex_data[3][i];
1347         }
1348
1349         *dataOut = vertex;
1350 }
1351 #endif
1352
1353
1354 void Playback3D::do_mask_sync(Playback3DCommand *command)
1355 {
1356 #ifdef HAVE_GL
1357         command->canvas->lock_canvas("Playback3D::do_mask_sync");
1358         if(command->canvas->get_canvas())
1359         {
1360                 BC_WindowBase *window = command->canvas->get_canvas();
1361                 window->lock_window("Playback3D::do_mask_sync");
1362                 window->enable_opengl();
1363                 
1364                 switch(command->frame->get_opengl_state())
1365                 {
1366                         case VFrame::RAM:
1367 // Time to upload to the texture
1368                                 command->frame->to_texture();
1369                                 break;
1370
1371                         case VFrame::SCREEN:
1372 // Read back from PBuffer
1373 // Bind context to pbuffer
1374                                 command->frame->enable_opengl();
1375                                 command->frame->screen_to_texture();
1376                                 break;
1377                 }
1378
1379
1380
1381 // Create PBuffer and draw the mask on it
1382                 command->frame->enable_opengl();
1383
1384 // Initialize coordinate system
1385                 int w = command->frame->get_w();
1386                 int h = command->frame->get_h();
1387                 command->frame->init_screen();
1388                 int value = command->keyframe_set->get_value(command->start_position_project,
1389                         PLAY_FORWARD);
1390                 float feather = command->keyframe_set->get_feather(command->start_position_project,
1391                         PLAY_FORWARD);
1392
1393 // Clear screen
1394                 glDisable(GL_TEXTURE_2D);
1395                 if(command->default_auto->mode == MASK_MULTIPLY_ALPHA)
1396                 {
1397                         glClearColor(0.0, 0.0, 0.0, 0.0);
1398                         glColor4f((float)value / 100, 
1399                                 (float)value / 100, 
1400                                 (float)value / 100, 
1401                                 1.0);
1402                 }
1403                 else
1404                 {
1405                         glClearColor(1.0, 1.0, 1.0, 1.0);
1406                         glColor4f((float)1.0 - (float)value / 100, 
1407                                 (float)1.0 - (float)value / 100, 
1408                                 (float)1.0 - (float)value / 100, 
1409                                 1.0);
1410                 }
1411                 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1412
1413                 
1414 // Draw mask with scaling to simulate feathering
1415                 GLUtesselator *tesselator = gluNewTess();
1416                 gluTessProperty(tesselator, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);
1417                 gluTessCallback(tesselator, GLU_TESS_VERTEX, (GLvoid (*) ( )) &glVertex3dv);
1418                 gluTessCallback(tesselator, GLU_TESS_BEGIN, (GLvoid (*) ( )) &glBegin);
1419                 gluTessCallback(tesselator, GLU_TESS_END, (GLvoid (*) ( )) &glEnd);
1420                 gluTessCallback(tesselator, GLU_TESS_COMBINE, (GLvoid (*) ( ))&combine_callback);
1421
1422
1423 // Draw every submask as a new polygon
1424                 int total_submasks = command->keyframe_set->total_submasks(
1425                         command->start_position_project, 
1426                         PLAY_FORWARD);
1427                 float scale = feather + 1;
1428                 int display_list = glGenLists(1);
1429                 glNewList(display_list, GL_COMPILE);
1430                 for(int k = 0; k < total_submasks; k++)
1431                 {
1432                         gluTessBeginPolygon(tesselator, NULL);
1433                         gluTessBeginContour(tesselator);
1434                         ArrayList<MaskPoint*> *points = new ArrayList<MaskPoint*>;
1435                         command->keyframe_set->get_points(points, 
1436                                 k, 
1437                                 command->start_position_project, 
1438                                 PLAY_FORWARD);
1439
1440                         int first_point = 0;
1441 // Need to tabulate every vertex in persistent memory because
1442 // gluTessVertex doesn't copy them.
1443                         ArrayList<GLdouble*> coords;
1444                         for(int i = 0; i < points->total; i++)
1445                         {
1446                                 MaskPoint *point1 = points->values[i];
1447                                 MaskPoint *point2 = (i >= points->total - 1) ? 
1448                                         points->values[0] : 
1449                                         points->values[i + 1];
1450
1451
1452 // This is very slow.
1453                                 float x, y;
1454                                 int segments = (int)(sqrt(SQR(point1->x - point2->x) + SQR(point1->y - point2->y)));
1455                                 if(point1->control_x2 == 0 &&
1456                                         point1->control_y2 == 0 &&
1457                                         point2->control_x1 == 0 &&
1458                                         point2->control_y1 == 0)
1459                                         segments = 1;
1460
1461                                 float x0 = point1->x;
1462                                 float y0 = point1->y;
1463                                 float x1 = point1->x + point1->control_x2;
1464                                 float y1 = point1->y + point1->control_y2;
1465                                 float x2 = point2->x + point2->control_x1;
1466                                 float y2 = point2->y + point2->control_y1;
1467                                 float x3 = point2->x;
1468                                 float y3 = point2->y;
1469
1470                                 for(int j = 0; j <= segments; j++)
1471                                 {
1472                                         float t = (float)j / segments;
1473                                         float tpow2 = t * t;
1474                                         float tpow3 = t * t * t;
1475                                         float invt = 1 - t;
1476                                         float invtpow2 = invt * invt;
1477                                         float invtpow3 = invt * invt * invt;
1478
1479                                         x = (        invtpow3 * x0
1480                                                 + 3 * t     * invtpow2 * x1
1481                                                 + 3 * tpow2 * invt     * x2 
1482                                                 +     tpow3            * x3);
1483                                         y = (        invtpow3 * y0 
1484                                                 + 3 * t     * invtpow2 * y1
1485                                                 + 3 * tpow2 * invt     * y2 
1486                                                 +     tpow3            * y3);
1487
1488
1489                                         if(j > 0 || first_point)
1490                                         {
1491                                                 GLdouble *coord = new GLdouble[3];
1492                                                 coord[0] = x / scale;
1493                                                 coord[1] = -h + y / scale;
1494                                                 coord[2] = 0;
1495                                                 coords.append(coord);
1496                                                 first_point = 0;
1497                                         }
1498                                 }
1499                         }
1500
1501 // Now that we know the total vertices, send them to GLU
1502                         for(int i = 0; i < coords.total; i++)
1503                                 gluTessVertex(tesselator, coords.values[i], coords.values[i]);
1504
1505                         gluTessEndContour(tesselator);
1506                         gluTessEndPolygon(tesselator);
1507                         points->remove_all_objects();
1508                         delete points;
1509                         coords.remove_all_objects();
1510                 }
1511                 glEndList();
1512                 glCallList(display_list);
1513                 glDeleteLists(display_list, 1);
1514
1515                 glColor4f(1, 1, 1, 1);
1516
1517
1518 // Read mask into temporary texture.
1519 // For feathering, just read the part of the screen after the downscaling.
1520
1521
1522                 float w_scaled = w / scale;
1523                 float h_scaled = h / scale;
1524 // Don't vary the texture size according to scaling because that 
1525 // would waste memory.
1526 // This enables and binds the temporary texture.
1527                 glActiveTexture(GL_TEXTURE1);
1528                 BC_Texture::new_texture(&temp_texture,
1529                         w, 
1530                         h, 
1531                         command->frame->get_color_model());
1532                 temp_texture->bind(1);
1533                 glReadBuffer(GL_BACK);
1534
1535 // Need to add extra size to fill in the bottom right
1536                 glCopyTexSubImage2D(GL_TEXTURE_2D,
1537                         0,
1538                         0,
1539                         0,
1540                         0,
1541                         0,
1542                         (int)MIN(w_scaled + 2, w),
1543                         (int)MIN(h_scaled + 2, h));
1544
1545                 command->frame->bind_texture(0);
1546
1547
1548 // For feathered masks, use a shader to multiply.
1549 // For unfeathered masks, we could use a stencil buffer 
1550 // for further optimization but we also need a YUV algorithm.
1551                 unsigned int frag_shader = 0;
1552                 switch(temp_texture->get_texture_components())
1553                 {
1554                         case 3: 
1555                                 if(command->frame->get_color_model() == BC_YUV888)
1556                                         frag_shader = VFrame::make_shader(0,
1557                                                 multiply_yuvmask3_frag,
1558                                                 0);
1559                                 else
1560                                         frag_shader = VFrame::make_shader(0,
1561                                                 multiply_mask3_frag,
1562                                                 0);
1563                                 break;
1564                         case 4: 
1565                                 frag_shader = VFrame::make_shader(0,
1566                                         multiply_mask4_frag,
1567                                         0);
1568                                 break;
1569                 }
1570
1571                 if(frag_shader)
1572                 {
1573                         int variable;
1574                         glUseProgram(frag_shader);
1575                         if((variable = glGetUniformLocation(frag_shader, "tex")) >= 0)
1576                                 glUniform1i(variable, 0);
1577                         if((variable = glGetUniformLocation(frag_shader, "tex1")) >= 0)
1578                                 glUniform1i(variable, 1);
1579                         if((variable = glGetUniformLocation(frag_shader, "scale")) >= 0)
1580                                 glUniform1f(variable, scale);
1581                 }
1582
1583
1584
1585 // Write texture to PBuffer with multiply and scaling for feather.
1586
1587                 
1588                 command->frame->draw_texture(0, 0, w, h, 0, 0, w, h);
1589                 command->frame->set_opengl_state(VFrame::SCREEN);
1590
1591
1592 // Disable temp texture
1593                 glUseProgram(0);
1594
1595                 glActiveTexture(GL_TEXTURE1);
1596                 glDisable(GL_TEXTURE_2D);
1597                 delete temp_texture;
1598                 temp_texture = 0;
1599
1600                 glActiveTexture(GL_TEXTURE0);
1601                 glDisable(GL_TEXTURE_2D);
1602
1603 // Default drawable
1604                 window->enable_opengl();
1605                 window->unlock_window();
1606         }
1607         command->canvas->unlock_canvas();
1608 #endif
1609 }
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620 void Playback3D::convert_cmodel(Canvas *canvas, 
1621         VFrame *output, 
1622         int dst_cmodel)
1623 {
1624 // Do nothing if colormodels are equivalent in OpenGL & the image is in hardware.
1625         int src_cmodel = output->get_color_model();
1626         if(
1627                 (output->get_opengl_state() == VFrame::TEXTURE ||
1628                 output->get_opengl_state() == VFrame::SCREEN) &&
1629 // OpenGL has no floating point.
1630                 ( (src_cmodel == BC_RGB888 && dst_cmodel == BC_RGB_FLOAT) ||
1631                   (src_cmodel == BC_RGBA8888 && dst_cmodel == BC_RGBA_FLOAT) ||
1632                   (src_cmodel == BC_RGB_FLOAT && dst_cmodel == BC_RGB888) ||
1633                   (src_cmodel == BC_RGBA_FLOAT && dst_cmodel == BC_RGBA8888) ||
1634 // OpenGL sets alpha to 1 on import
1635                   (src_cmodel == BC_RGB888 && dst_cmodel == BC_RGBA8888) ||
1636                   (src_cmodel == BC_YUV888 && dst_cmodel == BC_YUVA8888) ||
1637                   (src_cmodel == BC_RGB_FLOAT && dst_cmodel == BC_RGBA_FLOAT) )
1638                 ) return;
1639
1640
1641
1642         Playback3DCommand command;
1643         command.command = Playback3DCommand::CONVERT_CMODEL;
1644         command.canvas = canvas;
1645         command.frame = output;
1646         command.dst_cmodel = dst_cmodel;
1647         send_command(&command);
1648 }
1649
1650 void Playback3D::convert_cmodel_sync(Playback3DCommand *command)
1651 {
1652 #ifdef HAVE_GL
1653         command->canvas->lock_canvas("Playback3D::convert_cmodel_sync");
1654
1655         if(command->canvas->get_canvas())
1656         {
1657                 BC_WindowBase *window = command->canvas->get_canvas();
1658                 window->lock_window("Playback3D::convert_cmodel_sync");
1659                 window->enable_opengl();
1660
1661 // Import into hardware
1662                 command->frame->enable_opengl();
1663                 command->frame->init_screen();
1664                 command->frame->to_texture();
1665
1666 // Colormodel permutation
1667                 const char *shader = 0;
1668                 int src_cmodel = command->frame->get_color_model();
1669                 int dst_cmodel = command->dst_cmodel;
1670                 typedef struct
1671                 {
1672                         int src;
1673                         int dst;
1674                         const char *shader;
1675                 } cmodel_shader_table_t;
1676                 static cmodel_shader_table_t cmodel_shader_table[]  = 
1677                 {
1678                         { BC_RGB888, BC_YUV888, rgb_to_yuv_frag },
1679                         { BC_RGB888, BC_YUVA8888, rgb_to_yuv_frag },
1680                         { BC_RGBA8888, BC_RGB888, rgba_to_rgb_frag },
1681                         { BC_RGBA8888, BC_RGB_FLOAT, rgba_to_rgb_frag },
1682                         { BC_RGBA8888, BC_YUV888, rgba_to_yuv_frag },
1683                         { BC_RGBA8888, BC_YUVA8888, rgb_to_yuv_frag },
1684                         { BC_RGB_FLOAT, BC_YUV888, rgb_to_yuv_frag },
1685                         { BC_RGB_FLOAT, BC_YUVA8888, rgb_to_yuv_frag },
1686                         { BC_RGBA_FLOAT, BC_RGB888, rgba_to_rgb_frag },
1687                         { BC_RGBA_FLOAT, BC_RGB_FLOAT, rgba_to_rgb_frag },
1688                         { BC_RGBA_FLOAT, BC_YUV888, rgba_to_yuv_frag },
1689                         { BC_RGBA_FLOAT, BC_YUVA8888, rgb_to_yuv_frag },
1690                         { BC_YUV888, BC_RGB888, yuv_to_rgb_frag },
1691                         { BC_YUV888, BC_RGBA8888, yuv_to_rgb_frag },
1692                         { BC_YUV888, BC_RGB_FLOAT, yuv_to_rgb_frag },
1693                         { BC_YUV888, BC_RGBA_FLOAT, yuv_to_rgb_frag },
1694                         { BC_YUVA8888, BC_RGB888, yuva_to_rgb_frag },
1695                         { BC_YUVA8888, BC_RGBA8888, yuv_to_rgb_frag },
1696                         { BC_YUVA8888, BC_RGB_FLOAT, yuva_to_rgb_frag },
1697                         { BC_YUVA8888, BC_RGBA_FLOAT, yuv_to_rgb_frag },
1698                         { BC_YUVA8888, BC_YUV888, yuva_to_yuv_frag },
1699                 };
1700
1701                 int table_size = sizeof(cmodel_shader_table) / sizeof(cmodel_shader_table_t);
1702                 for(int i = 0; i < table_size; i++)
1703                 {
1704                         if(cmodel_shader_table[i].src == src_cmodel &&
1705                                 cmodel_shader_table[i].dst == dst_cmodel)
1706                         {
1707                                 shader = cmodel_shader_table[i].shader;
1708                                 break;
1709                         }
1710                 }
1711
1712 // printf("Playback3D::convert_cmodel_sync %d %d %d shader=\n%s", 
1713 // __LINE__, 
1714 // command->frame->get_color_model(), 
1715 // command->dst_cmodel,
1716 // shader);
1717
1718                 if(shader)
1719                 {
1720 //printf("Playback3D::convert_cmodel_sync %d\n", __LINE__);
1721                         command->frame->bind_texture(0);
1722                         unsigned int shader_id = -1;
1723                         if(shader)
1724                         {
1725                                 shader_id = VFrame::make_shader(0,
1726                                         shader,
1727                                         0);
1728                                 glUseProgram(shader_id);
1729                                 glUniform1i(glGetUniformLocation(shader_id, "tex"), 0);
1730                         }
1731
1732                         command->frame->draw_texture();
1733
1734                         if(shader) glUseProgram(0);
1735
1736                         command->frame->set_opengl_state(VFrame::SCREEN);
1737                 }
1738
1739                 window->unlock_window();
1740         }
1741
1742         command->canvas->unlock_canvas();
1743 #endif // HAVE_GL
1744 }
1745
1746 void Playback3D::do_fade(Canvas *canvas, VFrame *frame, float fade)
1747 {
1748         Playback3DCommand command;
1749         command.command = Playback3DCommand::DO_FADE;
1750         command.canvas = canvas;
1751         command.frame = frame;
1752         command.alpha = fade;
1753         send_command(&command);
1754 }
1755
1756 void Playback3D::do_fade_sync(Playback3DCommand *command)
1757 {
1758 #ifdef HAVE_GL
1759         command->canvas->lock_canvas("Playback3D::do_mask_sync");
1760         if(command->canvas->get_canvas())
1761         {
1762                 BC_WindowBase *window = command->canvas->get_canvas();
1763                 window->lock_window("Playback3D::do_fade_sync");
1764                 window->enable_opengl();
1765
1766                 switch(command->frame->get_opengl_state())
1767                 {
1768                         case VFrame::RAM:
1769                                 command->frame->to_texture();
1770                                 break;
1771
1772                         case VFrame::SCREEN:
1773 // Read back from PBuffer
1774 // Bind context to pbuffer
1775                                 command->frame->enable_opengl();
1776                                 command->frame->screen_to_texture();
1777                                 break;
1778                 }
1779
1780
1781                 command->frame->enable_opengl();
1782                 command->frame->init_screen();
1783                 command->frame->bind_texture(0);
1784
1785 //              glClearColor(0.0, 0.0, 0.0, 0.0);
1786 //              glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1787                 glDisable(GL_BLEND);
1788                 unsigned int frag_shader = 0;
1789                 switch(command->frame->get_color_model())
1790                 {
1791 // For the alpha colormodels, the native function seems to multiply the 
1792 // components by the alpha instead of just the alpha.
1793                         case BC_RGBA8888:
1794                         case BC_RGBA_FLOAT:
1795                         case BC_YUVA8888:
1796                                 frag_shader = VFrame::make_shader(0, fade_rgba_frag, 0);
1797                                 break;
1798
1799                         case BC_RGB888:
1800                                 glEnable(GL_BLEND);
1801                                 glBlendFunc(GL_SRC_ALPHA, GL_ZERO);
1802                                 glColor4f(command->alpha, command->alpha, command->alpha, 1);
1803                                 break;
1804
1805
1806                         case BC_YUV888:
1807                                 frag_shader = VFrame::make_shader(0, fade_yuv_frag, 0);
1808                                 break;
1809                 }
1810
1811
1812                 if(frag_shader)
1813                 {
1814                         glUseProgram(frag_shader);
1815                         int variable;
1816                         if((variable = glGetUniformLocation(frag_shader, "tex")) >= 0)
1817                                 glUniform1i(variable, 0);
1818                         if((variable = glGetUniformLocation(frag_shader, "alpha")) >= 0)
1819                                 glUniform1f(variable, command->alpha);
1820                 }
1821
1822                 command->frame->draw_texture();
1823                 command->frame->set_opengl_state(VFrame::SCREEN);
1824
1825                 if(frag_shader)
1826                 {
1827                         glUseProgram(0);
1828                 }
1829
1830                 glColor4f(1, 1, 1, 1);
1831                 glDisable(GL_BLEND);
1832
1833                 window->unlock_window();
1834         }
1835         command->canvas->unlock_canvas();
1836 #endif
1837 }
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849 int Playback3D::run_plugin(Canvas *canvas, PluginClient *client)
1850 {
1851         Playback3DCommand command;
1852         command.command = Playback3DCommand::PLUGIN;
1853         command.canvas = canvas;
1854         command.plugin_client = client;
1855         return send_command(&command);
1856 }
1857
1858 void Playback3D::run_plugin_sync(Playback3DCommand *command)
1859 {
1860         command->canvas->lock_canvas("Playback3D::run_plugin_sync");
1861         if(command->canvas->get_canvas())
1862         {
1863                 BC_WindowBase *window = command->canvas->get_canvas();
1864                 window->lock_window("Playback3D::run_plugin_sync");
1865                 window->enable_opengl();
1866
1867                 command->result = ((PluginVClient*)command->plugin_client)->handle_opengl();
1868
1869                 window->unlock_window();
1870         }
1871         command->canvas->unlock_canvas();
1872 }
1873
1874