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