4 * Copyright (C) 2008-2017 Adam Williams <broadcast at earthling dot net>
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.
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.
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
24 #include "bccapture.h"
25 #include "bccmodels.h"
26 #include "bcsignals.h"
29 #include "edlsession.h"
32 #include "maskautos.h"
34 #include "mwindowgui.h"
35 #include "playback3d.h"
36 #include "playbackconfig.h"
37 #include "preferences.h"
38 #include "recordconfig.h"
39 #include "strategies.inc"
40 #include "vdevicex11.h"
42 #include "videodevice.h"
43 #include "videowindow.h"
44 #include "videowindowgui.h"
49 VDeviceX11::VDeviceX11(VideoDevice *device, Canvas *output)
53 this->output = output;
56 VDeviceX11::~VDeviceX11()
61 int VDeviceX11::reset_parameters()
78 color_model_selected = 0;
81 for( int i = 0; i < SCREENCAP_BORDERS; i++ ) {
82 screencap_border[i] = 0;
87 int VDeviceX11::open_input()
89 //printf("VDeviceX11::open_input 1\n");
90 capture_bitmap = new BC_Capture(device->in_config->w,
92 device->in_config->screencapture_display);
93 //printf("VDeviceX11::open_input 2\n");
96 device->mwindow->gui->lock_window("VDeviceX11::close_all");
98 screencap_border[0] = new BC_Popup(device->mwindow->gui,
99 device->input_x - SCREENCAP_PIXELS, device->input_y - SCREENCAP_PIXELS,
100 device->in_config->w + SCREENCAP_PIXELS * 2, SCREENCAP_PIXELS,
102 screencap_border[1] = new BC_Popup(device->mwindow->gui,
103 device->input_x - SCREENCAP_PIXELS, device->input_y,
104 SCREENCAP_PIXELS, device->in_config->h,
106 screencap_border[2] = new BC_Popup(device->mwindow->gui,
107 device->input_x - SCREENCAP_PIXELS, device->input_y + device->in_config->h,
108 device->in_config->w + SCREENCAP_PIXELS * 2, SCREENCAP_PIXELS,
110 screencap_border[3] = new BC_Popup(device->mwindow->gui,
111 device->input_x + device->in_config->w, device->input_y,
112 SCREENCAP_PIXELS, device->in_config->h,
114 usleep(500000); // avoids a bug in gnome-shell 2017/10/19
116 for( int i=0; i<SCREENCAP_BORDERS; ++i )
117 screencap_border[i]->show_window(0);
119 device->mwindow->gui->flush();
120 device->mwindow->gui->unlock_window();
125 int VDeviceX11::open_output()
128 output->lock_canvas("VDeviceX11::open_output");
129 output->get_canvas()->lock_window("VDeviceX11::open_output");
130 if( !device->single_frame )
131 output->start_video();
133 output->start_single();
134 output->get_canvas()->unlock_window();
136 // Enable opengl in the first routine that needs it, to reduce the complexity.
137 output->unlock_canvas();
143 int VDeviceX11::output_visible()
145 if( !output ) return 0;
147 output->lock_canvas("VDeviceX11::output_visible");
148 if( output->get_canvas()->get_hidden() ) {
149 output->unlock_canvas();
153 output->unlock_canvas();
159 int VDeviceX11::close_all()
162 output->lock_canvas("VDeviceX11::close_all 1");
163 output->get_canvas()->lock_window("VDeviceX11::close_all 1");
166 if( output && output_frame ) {
167 output->update_refresh(device, output_frame);
168 if( device->single_frame )
169 output->draw_refresh();
172 delete bitmap; bitmap = 0;
173 delete output_frame; output_frame = 0;
174 delete capture_bitmap; capture_bitmap = 0;
177 // Update the status bug
178 if( !device->single_frame ) {
179 output->stop_video();
182 output->stop_single();
185 output->get_canvas()->unlock_window();
186 output->unlock_canvas();
189 if( device->mwindow ) {
190 device->mwindow->gui->lock_window("VDeviceX11::close_all");
191 for( int i=0; i<SCREENCAP_BORDERS; ++i ) {
192 delete screencap_border[i];
193 screencap_border[i] = 0;
195 device->mwindow->gui->unlock_window();
203 int VDeviceX11::read_buffer(VFrame *frame)
205 //printf("VDeviceX11::read_buffer %d colormodel=%d\n", __LINE__, frame->get_color_model());
206 device->mwindow->gui->lock_window("VDeviceX11::close_all");
208 screencap_border[0]->reposition_window(device->input_x - SCREENCAP_PIXELS,
209 device->input_y - SCREENCAP_PIXELS);
210 screencap_border[1]->reposition_window(device->input_x - SCREENCAP_PIXELS,
212 screencap_border[2]->reposition_window(device->input_x - SCREENCAP_PIXELS,
213 device->input_y + device->in_config->h);
214 screencap_border[3]->reposition_window(device->input_x + device->in_config->w,
216 device->mwindow->gui->flush();
217 device->mwindow->gui->unlock_window();
220 capture_bitmap->capture_frame(frame,
221 device->input_x, device->input_y, device->do_cursor);
226 int VDeviceX11::get_best_colormodel(Asset *asset)
228 return File::get_best_colormodel(asset, SCREENCAPTURE);
233 int VDeviceX11::get_display_colormodel(int file_colormodel)
237 if( device->out_config->driver == PLAYBACK_X11_GL ) {
238 if( file_colormodel == BC_RGB888 ||
239 file_colormodel == BC_RGBA8888 ||
240 file_colormodel == BC_YUV888 ||
241 file_colormodel == BC_YUVA8888 ||
242 file_colormodel == BC_RGB_FLOAT ||
243 file_colormodel == BC_RGBA_FLOAT ) {
244 return file_colormodel;
250 if( !device->single_frame ) {
251 switch( file_colormodel ) {
255 result = file_colormodel;
260 // 2 more colormodels are supported by OpenGL
261 if( device->out_config->driver == PLAYBACK_X11_GL ) {
262 if( file_colormodel == BC_RGB_FLOAT ||
263 file_colormodel == BC_RGBA_FLOAT )
264 result = file_colormodel;
268 switch( file_colormodel ) {
275 result = file_colormodel;
279 output->lock_canvas("VDeviceX11::get_display_colormodel");
280 result = output->get_canvas()->get_color_model();
281 output->unlock_canvas();
290 void VDeviceX11::new_output_buffer(VFrame **result, int file_colormodel, EDL *edl)
292 // printf("VDeviceX11::new_output_buffer %d hardware_scaling=%d\n",
293 // __LINE__, bitmap ? bitmap->hardware_scaling() : 0);
294 output->lock_canvas("VDeviceX11::new_output_buffer");
295 output->get_canvas()->lock_window("VDeviceX11::new_output_buffer 1");
297 // Get the best colormodel the display can handle.
298 int display_colormodel = get_display_colormodel(file_colormodel);
300 //printf("VDeviceX11::new_output_buffer %d file_colormodel=%d display_colormodel=%d\n",
301 // __LINE__, file_colormodel, display_colormodel);
302 // Only create OpenGL Pbuffer and texture.
303 if( device->out_config->driver == PLAYBACK_X11_GL ) {
304 // Create bitmap for initial load into texture.
305 // Not necessary to do through Playback3D.....yet
306 if( !output_frame ) {
307 output_frame = new VFrame(device->out_w, device->out_h, file_colormodel);
310 window_id = output->get_canvas()->get_id();
311 output_frame->set_opengl_state(VFrame::RAM);
314 output->get_transfers(edl,
315 output_x1, output_y1, output_x2, output_y2,
316 canvas_x1, canvas_y1, canvas_x2, canvas_y2,
317 // Canvas may be a different size than the temporary bitmap for pure software
319 canvas_w = canvas_x2 - canvas_x1;
320 canvas_h = canvas_y2 - canvas_y1;
321 // can the direct frame be used?
322 int direct_supported =
323 device->out_config->use_direct_x11 &&
324 !output->xscroll && !output->yscroll &&
325 output_x1 == 0 && output_x2 == device->out_w &&
326 output_y1 == 0 && output_y2 == device->out_h;
328 // file wants direct frame but we need a temp
329 if( !direct_supported && file_colormodel == BC_BGR8888 )
330 file_colormodel = BC_RGB888;
332 // Conform existing bitmap to new colormodel and output size
334 // printf("VDeviceX11::new_output_buffer %d bitmap=%dx%d canvas=%dx%d canvas=%dx%d\n",
335 // __LINE__, bitmap->get_w(), bitmap->get_h(), canvas_w, canvas_h,);
337 bitmap->get_w() != canvas_w ||
338 bitmap->get_h() != canvas_h );
340 // Restart if output size changed or output colormodel changed.
341 // May have to recreate if transferring between windowed and fullscreen.
342 if( !color_model_selected ||
343 file_colormodel != output_frame->get_color_model() ||
344 (!bitmap->hardware_scaling() && size_change) ) {
345 //printf("VDeviceX11::new_output_buffer %d file_colormodel=%d prev "
346 // "file_colormodel=%d bitmap=%p output_frame=%p\n", __LINE__,
347 // file_colormodel, output_frame->get_color_model(), bitmap, output_frame);
348 delete bitmap; bitmap = 0;
349 delete output_frame; output_frame = 0;
350 // Clear borders if size changed
352 //printf("VDeviceX11::new_output_buffer %d w=%d h=%d "
353 // "canvas_x1=%d canvas_y1=%d canvas_x2=%d canvas_y2=%d\n",
354 // __LINE__, // (int)output->w, (int)output->h,
355 // (int)canvas_x1, (int)canvas_y1, (int)canvas_x2, (int)canvas_y2);
356 output->get_canvas()->set_color(BLACK);
358 if( canvas_y1 > 0 ) {
359 output->get_canvas()->draw_box(0, 0, output->w, canvas_y1);
360 output->get_canvas()->flash(0, 0, output->w, canvas_y1);
363 if( canvas_y2 < output->h ) {
364 output->get_canvas()->draw_box(0, canvas_y2, output->w, output->h - canvas_y2);
365 output->get_canvas()->flash(0, canvas_y2, output->w, output->h - canvas_y2);
368 if( canvas_x1 > 0 ) {
369 output->get_canvas()->draw_box(0, canvas_y1, canvas_x1, canvas_y2 - canvas_y1);
370 output->get_canvas()->flash(0, canvas_y1, canvas_x1, canvas_y2 - canvas_y1);
373 if( canvas_x2 < output->w ) {
374 output->get_canvas()->draw_box(canvas_x2, canvas_y1,
375 output->w - canvas_x2, canvas_y2 - canvas_y1);
376 output->get_canvas()->flash(canvas_x2, canvas_y1,
377 output->w - canvas_x2, canvas_y2 - canvas_y1);
386 bitmap_type = BITMAP_TEMP;
387 //printf("VDeviceX11::new_output_buffer %d file_colormodel=%d display_colormodel=%d\n",
388 // __LINE__, file_colormodel, display_colormodel);
390 // Try hardware accelerated
391 switch( display_colormodel ) {
392 // blit from the codec directly to the window, using the standard X11 color model.
393 // Must scale in the codec. No cropping
395 if( direct_supported ) {
396 bitmap_type = BITMAP_PRIMARY;
402 if( device->out_config->driver == PLAYBACK_X11_XV &&
403 output->get_canvas()->accel_available(display_colormodel, 0) &&
404 !output->use_scrollbars )
405 bitmap_type = BITMAP_PRIMARY;
409 if( device->out_config->driver == PLAYBACK_X11_XV &&
410 output->get_canvas()->accel_available(display_colormodel, 0) &&
411 !output->use_scrollbars )
412 bitmap_type = BITMAP_PRIMARY;
413 else if( device->out_config->driver == PLAYBACK_X11_XV &&
414 output->get_canvas()->accel_available(BC_YUV422, 0) ) {
415 bitmap = new BC_Bitmap(output->get_canvas(),
416 device->out_w, device->out_h, BC_YUV422, 1);
421 if( device->out_config->driver == PLAYBACK_X11_XV &&
422 output->get_canvas()->accel_available(display_colormodel, 0) &&
423 !output->use_scrollbars ) {
424 bitmap_type = BITMAP_PRIMARY;
426 else if( device->out_config->driver == PLAYBACK_X11_XV &&
427 output->get_canvas()->accel_available(BC_YUV422P, 0) ) {
428 bitmap = new BC_Bitmap(output->get_canvas(),
429 device->out_w, device->out_h, BC_YUV422P, 1);
433 if( bitmap_type == BITMAP_PRIMARY ) {
434 int bitmap_w = use_direct ? canvas_w : device->out_w;
435 int bitmap_h = use_direct ? canvas_h : device->out_h;
436 bitmap = new BC_Bitmap(output->get_canvas(),
437 bitmap_w, bitmap_h, display_colormodel, -1);
438 output_frame = new VFrame(bitmap,
439 bitmap_w, bitmap_h, display_colormodel, -1);
441 // Make an intermediate frame
443 display_colormodel = output->get_canvas()->get_color_model();
444 // printf("VDeviceX11::new_output_buffer %d creating temp display_colormodel=%d "
445 // "file_colormodel=%d %dx%d %dx%d %dx%d\n", __LINE__,
446 // display_colormodel, file_colormodel, device->out_w, device->out_h,
447 // output->get_canvas()->get_w(), output->get_canvas()->get_h(), canvas_w, canvas_h);
448 bitmap = new BC_Bitmap(output->get_canvas(),
449 canvas_w, canvas_h, display_colormodel, 1);
450 bitmap_type = BITMAP_TEMP;
453 if( bitmap_type == BITMAP_TEMP ) {
454 // Intermediate frame
455 //printf("VDeviceX11::new_output_buffer %d creating output_frame\n", __LINE__);
456 output_frame = new VFrame(device->out_w, device->out_h, file_colormodel);
458 color_model_selected = 1;
460 else if( bitmap_type == BITMAP_PRIMARY ) {
461 output_frame->set_memory(bitmap);
465 *result = output_frame;
466 //printf("VDeviceX11::new_output_buffer 10 %d\n", output->get_canvas()->get_window_lock());
468 output->get_canvas()->unlock_window();
469 output->unlock_canvas();
473 int VDeviceX11::start_playback()
475 // Record window is initialized when its monitor starts.
476 if( !device->single_frame )
477 output->start_video();
481 int VDeviceX11::stop_playback()
483 if( !device->single_frame )
484 output->stop_video();
485 // Record window goes back to monitoring
486 // get the last frame played and store it in the video_out
490 int VDeviceX11::write_buffer(VFrame *output_channels, EDL *edl)
492 output->lock_canvas("VDeviceX11::write_buffer");
493 output->get_canvas()->lock_window("VDeviceX11::write_buffer 1");
494 // if( device->out_config->driver == PLAYBACK_X11_GL &&
495 // output_frame->get_color_model() != BC_RGB888 ) {
496 // this is handled by overlay call in virtualvnode, using flatten alpha
497 // invoked when is_nested = -1 is passed to vdevicex11->overlay(...)
500 // printf("VDeviceX11::write_buffer %d %d bitmap_type=%d\n",
502 // output->get_canvas()->get_video_on(),
505 // int use_bitmap_extents = 0;
506 // canvas_w = -1; canvas_h = -1;
507 // // Canvas may be a different size than the temporary bitmap for pure software
508 // if( bitmap_type == BITMAP_TEMP && !bitmap->hardware_scaling() ) {
509 // canvas_w = bitmap->get_w();
510 // canvas_h = bitmap->get_h();
513 // output->get_transfers(edl,
514 // output_x1, output_y1, output_x2, output_y2,
515 // canvas_x1, canvas_y1, canvas_x2, canvas_y2,
516 // canvas_w, canvas_h);
518 // Convert colormodel
519 if( bitmap_type == BITMAP_TEMP ) {
520 // printf("VDeviceX11::write_buffer 1 %d %d, %d %d %d %d -> %d %d %d %d\n",
521 // output->w, output->h, in_x, in_y, in_w, in_h, out_x, out_y, out_w, out_h);
524 // printf("VDeviceX11::write_buffer %d output_channels=%p\n", __LINE__, output_channels);
525 // printf("VDeviceX11::write_buffer %d input color_model=%d output color_model=%d\n",
526 // __LINE__, output_channels->get_color_model(), bitmap->get_color_model());
527 if( bitmap->hardware_scaling() ) {
528 BC_CModels::transfer(bitmap->get_row_pointers(), output_channels->get_rows(), 0, 0, 0,
529 output_channels->get_y(), output_channels->get_u(), output_channels->get_v(),
530 0, 0, output_channels->get_w(), output_channels->get_h(),
531 0, 0, bitmap->get_w(), bitmap->get_h(),
532 output_channels->get_color_model(), bitmap->get_color_model(),
533 0, output_channels->get_w(), bitmap->get_w());
536 BC_CModels::transfer(bitmap->get_row_pointers(), output_channels->get_rows(), 0, 0, 0,
537 output_channels->get_y(), output_channels->get_u(), output_channels->get_v(),
538 (int)output_x1, (int)output_y1, (int)(output_x2 - output_x1), (int)(output_y2 - output_y1),
539 0, 0, (int)(canvas_x2 - canvas_x1), (int)(canvas_y2 - canvas_y1),
540 output_channels->get_color_model(), bitmap->get_color_model(),
541 0, output_channels->get_w(), bitmap->get_w());
545 //printf("VDeviceX11::write_buffer 4 %p\n", bitmap);
546 //for( i = 0; i < 1000; i += 4 ) bitmap->get_data()[i] = 128;
547 //printf("VDeviceX11::write_buffer 2 %d %d %d\n", bitmap_type,
548 // bitmap->get_color_model(),
549 // output->get_color_model());fflush(stdout);
551 // printf("VDeviceX11::write_buffer %d %dx%d %f %f %f %f -> %f %f %f %f\n",
552 // __LINE__, // output->w, output->h,
553 // output_x1, output_y1, output_x2, output_y2,
554 // canvas_x1, canvas_y1, canvas_x2, canvas_y2);
556 // Cause X server to display it
557 if( device->out_config->driver == PLAYBACK_X11_GL ) {
558 // Output is drawn in close_all if no video.
559 if( output->get_canvas()->get_video_on() ) {
560 canvas_w = -1; canvas_h = -1;
561 // Canvas may be a different size than the temporary bitmap for pure software
562 if( bitmap_type == BITMAP_TEMP &&
563 !bitmap->hardware_scaling() ) {
564 canvas_w = bitmap->get_w();
565 canvas_h = bitmap->get_h();
568 output->get_transfers(edl,
569 output_x1, output_y1, output_x2, output_y2,
570 canvas_x1, canvas_y1, canvas_x2, canvas_y2,
573 //printf("VDeviceX11::write_buffer %d\n", __LINE__);
574 // Draw output frame directly. Not used for compositing.
575 output->get_canvas()->unlock_window();
576 output->unlock_canvas();
577 output->mwindow->playback_3d->write_buffer(output, output_frame,
578 output_x1, output_y1, output_x2, output_y2,
579 canvas_x1, canvas_y1, canvas_x2, canvas_y2,
582 output->lock_canvas("VDeviceX11::write_buffer 2");
583 output->get_canvas()->lock_window("VDeviceX11::write_buffer 2");
587 if( bitmap->hardware_scaling() ) {
588 output->get_canvas()->draw_bitmap(bitmap, !device->single_frame,
589 (int)canvas_x1, (int)canvas_y1,
590 (int)(canvas_x2 - canvas_x1), (int)(canvas_y2 - canvas_y1),
591 (int)output_x1, (int)output_y1,
592 (int)(output_x2 - output_x1), (int)(output_y2 - output_y1),
596 //printf("VDeviceX11::write_buffer %d x=%d y=%d w=%d h=%d\n",
597 // __LINE__, (int)canvas_x1, (int)canvas_y1,
598 // output->get_canvas()->get_w(), output->get_canvas()->get_h());
600 output->get_canvas()->draw_bitmap(bitmap, !device->single_frame,
601 (int)canvas_x1, (int)canvas_y1,
602 (int)(canvas_x2 - canvas_x1), (int)(canvas_y2 - canvas_y1),
604 (int)(canvas_x2 - canvas_x1), (int)(canvas_y2 - canvas_y1),
606 //printf("VDeviceX11::write_buffer %d bitmap=%p\n", __LINE__, bitmap);
609 output->get_canvas()->unlock_window();
610 output->unlock_canvas();
615 void VDeviceX11::clear_output()
619 output->mwindow->playback_3d->clear_output(output,
620 output->get_canvas()->get_video_on() ? 0 : output_frame);
625 void VDeviceX11::clear_input(VFrame *frame)
627 this->output->mwindow->playback_3d->clear_input(this->output, frame);
630 void VDeviceX11::convert_cmodel(VFrame *output, int dst_cmodel)
632 this->output->mwindow->playback_3d->convert_cmodel(this->output,
637 void VDeviceX11::do_camera(VFrame *output, VFrame *input,
638 float in_x1, float in_y1, float in_x2, float in_y2,
639 float out_x1, float out_y1, float out_x2, float out_y2)
641 this->output->mwindow->playback_3d->do_camera(this->output,
643 in_x1, in_y1, in_x2, in_y2,
644 out_x1, out_y1, out_x2, out_y2);
648 void VDeviceX11::do_fade(VFrame *output_temp, float fade)
650 this->output->mwindow->playback_3d->do_fade(this->output, output_temp, fade);
653 bool VDeviceX11::can_mask(int64_t start_position_project, MaskAutos *keyframe_set)
656 MaskAuto *keyframe = (MaskAuto*)keyframe_set->
657 get_prev_auto(start_position_project, PLAY_FORWARD, current);
658 return keyframe->disable_opengl_masking ? 0 : 1;
661 void VDeviceX11::do_mask(VFrame *output_temp, int64_t start_position_project,
662 MaskAutos *keyframe_set, MaskAuto *keyframe, MaskAuto *default_auto)
664 this->output->mwindow->playback_3d->do_mask(output, output_temp,
665 start_position_project, keyframe_set, keyframe, default_auto);
668 void VDeviceX11::overlay(VFrame *output_frame, VFrame *input,
669 // This is the transfer from track to output frame
670 float in_x1, float in_y1, float in_x2, float in_y2,
671 float out_x1, float out_y1, float out_x2, float out_y2,
672 float alpha, // 0 - 1
673 int mode, EDL *edl, int is_nested)
675 int interpolation_type = edl->session->interpolation_type;
677 // printf("VDeviceX11::overlay 1:\n"
678 // "in_x1=%f in_y1=%f in_x2=%f in_y2=%f\n"
679 // "out_x1=%f out_y1=%f out_x2=%f out_y2=%f\n",
680 // in_x1, in_y1, in_x2, in_y2, out_x1, out_y1, out_x2, out_y2);
681 // Convert node coords to canvas coords in here
683 // If single frame playback or nested EDL, use full sized PBuffer as output.
684 if( device->single_frame || is_nested > 0 ) {
685 output->mwindow->playback_3d->overlay(output, input,
686 in_x1, in_y1, in_x2, in_y2,
687 out_x1, out_y1, out_x2, out_y2, alpha, // 0 - 1
688 mode, interpolation_type, output_frame, is_nested);
689 // printf("VDeviceX11::overlay 1 %p %d %d %d\n",
690 // output_frame, output_frame->get_w(), output_frame->get_h(),
691 // output_frame->get_opengl_state());
694 output->lock_canvas("VDeviceX11::overlay");
695 output->get_canvas()->lock_window("VDeviceX11::overlay");
697 // This is the transfer from output frame to canvas
698 output->get_transfers(edl,
699 output_x1, output_y1, output_x2, output_y2,
700 canvas_x1, canvas_y1, canvas_x2, canvas_y2,
703 output->get_canvas()->unlock_window();
704 output->unlock_canvas();
707 // Get transfer from track to canvas
708 float track_xscale = (out_x2 - out_x1) / (in_x2 - in_x1);
709 float track_yscale = (out_y2 - out_y1) / (in_y2 - in_y1);
710 float canvas_xscale = (float)(canvas_x2 - canvas_x1) / (output_x2 - output_x1);
711 float canvas_yscale = (float)(canvas_y2 - canvas_y1) / (output_y2 - output_y1);
714 // Get coordinates of canvas relative to track frame
715 float track_x1 = (float)(output_x1 - out_x1) / track_xscale + in_x1;
716 float track_y1 = (float)(output_y1 - out_y1) / track_yscale + in_y1;
717 float track_x2 = (float)(output_x2 - out_x2) / track_xscale + in_x2;
718 float track_y2 = (float)(output_y2 - out_y2) / track_yscale + in_y2;
720 // Clamp canvas coords to track boundary
722 float difference = -track_x1;
723 track_x1 += difference;
724 canvas_x1 += difference * track_xscale * canvas_xscale;
727 float difference = -track_y1;
728 track_y1 += difference;
729 canvas_y1 += difference * track_yscale * canvas_yscale;
732 if( track_x2 > input->get_w() ) {
733 float difference = track_x2 - input->get_w();
734 track_x2 -= difference;
735 canvas_x2 -= difference * track_xscale * canvas_xscale;
737 if( track_y2 > input->get_h() ) {
738 float difference = track_y2 - input->get_h();
739 track_y2 -= difference;
740 canvas_y2 -= difference * track_yscale * canvas_yscale;
743 // Overlay directly from track buffer to canvas, skipping output buffer
744 if( track_x2 > track_x1 && track_y2 > track_y1 &&
745 canvas_x2 > canvas_x1 && canvas_y2 > canvas_y1 ) {
746 output->mwindow->playback_3d->overlay(output, input,
747 track_x1, track_y1, track_x2, track_y2,
748 canvas_x1, canvas_y1, canvas_x2, canvas_y2, alpha, // 0 - 1
749 mode, interpolation_type, 0, is_nested);
754 void VDeviceX11::run_plugin(PluginClient *client)
756 output->mwindow->playback_3d->run_plugin(output, client);
759 void VDeviceX11::copy_frame(VFrame *dst, VFrame *src)
761 output->mwindow->playback_3d->copy_from(output, dst, src, 1);