From: Good Guy Date: Mon, 28 Mar 2016 23:07:04 +0000 (-0600) Subject: merge: mask fixes/upgrades, overlay plugin rework, popup menu tweak X-Git-Url: https://git.cinelerra-gg.org/git/?a=commitdiff_plain;h=21b49090a36821cfe97bdfc573c7fbacc80653d1;p=goodguy%2Fhistory.git merge: mask fixes/upgrades, overlay plugin rework, popup menu tweak --- diff --git a/cinelerra-5.1/bld_scripts/bld_dynamic.sh b/cinelerra-5.1/bld_scripts/bld_dynamic.sh index fdf54679..ad08e782 100755 --- a/cinelerra-5.1/bld_scripts/bld_dynamic.sh +++ b/cinelerra-5.1/bld_scripts/bld_dynamic.sh @@ -14,25 +14,25 @@ fi cd "$path/$dir/$bld" rm -rf "$proj" -git clone --depth 1 "git://git.cinelerra-cv.org/goodguy/cinelerra.git" "$proj" -#rsh host tar -C /mnt0/cinelerra5 -cf - cinelerra | tar -xf - -#mv cinelerra cinelerra5 +git clone "git://git.cinelerra-cv.org/goodguy/cinelerra.git" "$proj" +#rsh host tar -C /mnt0 -cf - cinelerra5 | tar -xf - if [ $? -ne 0 ]; then echo "git clone $proj failed" exit 1 fi cd "$proj/$base" -if [ "$dir" = "ubuntu" ]; then - echo "CFLAGS += -DPNG_SKIP_SETJMP_CHECK=1" >> global_config -fi -if [ "$dir" = "centos" ]; then - echo "EXTRA_LIBS += -lnuma" >> global_config - echo "CFLAGS += -D__STDC_CONSTANT_MACROS -D__STDC_LIMIT_MACROS" >> global_config -fi -if [ "$dir" = "suse" ]; then - echo "EXTRA_LIBS += -lnuma" >> global_config -fi +case "$dir" in + "ubuntu" | "mint" | "ub14" | "ub15") + echo "CFLAGS += -DPNG_SKIP_SETJMP_CHECK=1" >> global_config ;; + "centos") + echo "CFLAGS += -D__STDC_CONSTANT_MACROS -D__STDC_LIMIT_MACROS" >> global_config + echo "EXTRA_LIBS += -lnuma" >> global_config ;; + "suse" | "leap") + echo "EXTRA_LIBS += -lnuma" >> global_config ;; + "fedora") + echo "EXTRA_LIBS += -lnuma" >> global_config ;; +esac STATIC_LIBRARIES=0 ./configure >& log make >> log 2>&1 $@ diff --git a/cinelerra-5.1/bld_scripts/bld_prepare.sh b/cinelerra-5.1/bld_scripts/bld_prepare.sh index e276b8c5..65c40d2f 100755 --- a/cinelerra-5.1/bld_scripts/bld_prepare.sh +++ b/cinelerra-5.1/bld_scripts/bld_prepare.sh @@ -31,7 +31,20 @@ case "$dir" in yum -y install /tmp/$yasm rm -f /tmp/$yasm ;; -"suse") +"fedora") + dnf -y install nasm yasm libavc1394-devel libusb-devel flac-devel \ + libjpeg-devel libdv-devel libdvdnav-devel libdvdread-devel \ + libtheora-devel libiec61883-devel esound-devel uuid-devel \ + giflib-devel ncurses-devel ilmbase-devel fftw-devel OpenEXR-devel \ + libsndfile-devel libXft-devel libXinerama-devel libXv-devel \ + xorg-x11-fonts-misc xorg-x11-fonts-cyrillic xorg-x11-fonts-Type1 \ + xorg-x11-fonts-ISO8859-1-100dpi xorg-x11-fonts-ISO8859-1-75dpi \ + libpng-devel bzip2-devel zlib-devel kernel-headers libavc1394 \ + festival-devel libdc1394-devel libiec61883-devel esound-devel \ + flac-devel libsndfile-devel libtheora-devel linux-firmware \ + ivtv-firmware libvorbis-devel texinfo xz-devel lzma-devel cmake + ;; +"suse" | "leap") zypper -n install nasm gcc gcc-c++ zlib-devel texinfo libpng16-devel \ freeglut-devel libXv-devel alsa-devel libbz2-devel ncurses-devel \ libXinerama-devel freetype-devel libXft-devel giflib-devel ctags \ @@ -44,9 +57,9 @@ case "$dir" in ln -s libtermcap.so.2 /usr/lib64/libtermcap.so fi ;; -"ubuntu") - apt-get -y install apt-file sox nasm yasm g++ build-essential libz-dev texinfo \ - libpng-dev freeglut3-dev libxv-dev libasound2-dev libbz2-dev \ +"ubuntu" | "mint" | "ub14" | "ub15") + apt-get -y install apt-file sox nasm yasm g++ build-essential libz-dev \ + texinfo libpng-dev freeglut3-dev libxv-dev libasound2-dev libbz2-dev \ libncurses5-dev libxinerama-dev libfreetype6-dev libxft-dev libgif-dev \ libtiff5-dev exuberant-ctags ttf-bitstream-vera xfonts-75dpi xfonts-100dpi \ fonts-dejavu libopenexr-dev libavc1394-dev festival-dev fftw3-dev \ diff --git a/cinelerra-5.1/bld_scripts/bld_static.sh b/cinelerra-5.1/bld_scripts/bld_static.sh index e41df88c..cca4acfc 100755 --- a/cinelerra-5.1/bld_scripts/bld_static.sh +++ b/cinelerra-5.1/bld_scripts/bld_static.sh @@ -14,25 +14,25 @@ fi cd "$path/$dir/$bld" rm -rf "$proj" -git clone --depth 1 "git://git.cinelerra-cv.org/goodguy/cinelerra.git" "$proj" -#rsh host tar -C /mnt0/cinelerra5 -cf - cinelerra | tar -xf - -#mv cinelerra cinelerra5 +git clone "git://git.cinelerra-cv.org/goodguy/cinelerra.git" "$proj" +#rsh host tar -C /mnt0 -cf - cinelerra5 | tar -xf - if [ $? -ne 0 ]; then echo "git clone $proj failed" exit 1 fi cd "$proj/$base" -if [ "$dir" = "ubuntu" ]; then - echo "CFLAGS += -DPNG_SKIP_SETJMP_CHECK=1" >> global_config -fi -if [ "$dir" = "centos" ]; then - echo "EXTRA_LIBS += -lnuma" >> global_config - echo "CFLAGS += -D__STDC_CONSTANT_MACROS -D__STDC_LIMIT_MACROS" >> global_config -fi -if [ "$dir" = "suse" ]; then - echo "EXTRA_LIBS += -lnuma" >> global_config -fi +case "$dir" in + "ubuntu" | "mint" | "ub14" | "ub15") + echo "CFLAGS += -DPNG_SKIP_SETJMP_CHECK=1" >> global_config ;; + "centos") + echo "CFLAGS += -D__STDC_CONSTANT_MACROS -D__STDC_LIMIT_MACROS" >> global_config + echo "EXTRA_LIBS += -lnuma" >> global_config ;; + "suse" | "leap") + echo "EXTRA_LIBS += -lnuma" >> global_config ;; + "fedora") + echo "EXTRA_LIBS += -lnuma" >> global_config ;; +esac STATIC_LIBRARIES=1 ./configure >& log make >> log 2>&1 $@ diff --git a/cinelerra-5.1/cinelerra/commercials.C b/cinelerra-5.1/cinelerra/commercials.C index e74275b5..a08ec029 100644 --- a/cinelerra-5.1/cinelerra/commercials.C +++ b/cinelerra-5.1/cinelerra/commercials.C @@ -533,7 +533,7 @@ cut_edit(Track *track, Edit *edit, int64_t clip_start, int64_t clip_end) } } // cut edit - Edit *next_edit = track->edits->split_edit(edit, cut_start); + Edit *next_edit = edit->edits->split_edit(cut_start); int64_t cut_length = cut_end - cut_start; next_edit->length -= cut_length; next_edit->startsource += cut_length; diff --git a/cinelerra-5.1/cinelerra/cwindowgui.C b/cinelerra-5.1/cinelerra/cwindowgui.C index 8df8e594..13a1ca76 100644 --- a/cinelerra-5.1/cinelerra/cwindowgui.C +++ b/cinelerra-5.1/cinelerra/cwindowgui.C @@ -1369,17 +1369,17 @@ int CWindowCanvas::do_ruler(int draw, } -static inline bool test_bbox(int cx, int cy, int tx, int ty) -{ - return (llabs(cx-tx) < (CONTROL_W/2) && llabs(cy-ty) < (CONTROL_H/2)); -} - static inline double line_dist(float cx,float cy, float tx,float ty) { - int dx = tx-cx, dy = ty-cy; + double dx = tx-cx, dy = ty-cy; return sqrt(dx*dx + dy*dy); } +static inline bool test_bbox(int cx, int cy, int tx, int ty) +{ +// printf("test_bbox %d,%d - %d,%d = %f\n",cx,cy,tx,ty,line_dist(cx,cy,tx,ty)); + return (llabs(cx-tx) < CONTROL_W/2 && llabs(cy-ty) < CONTROL_H/2); +} int CWindowCanvas::do_mask(int &redraw, int &rerender, int button_press, int cursor_motion, int draw) @@ -1459,15 +1459,14 @@ int CWindowCanvas::do_mask(int &redraw, int &rerender, // Get position of cursor relative to mask - float cursor_x = get_cursor_x(); - float cursor_y = get_cursor_y(); - canvas_to_output(mwindow->edl, 0, cursor_x, cursor_y); + float cursor_x = get_cursor_x(), cursor_y = get_cursor_y(); + float mask_cursor_x = cursor_x, mask_cursor_y = cursor_y; + canvas_to_output(mwindow->edl, 0, mask_cursor_x, mask_cursor_y); projector_x += mwindow->edl->session->output_w / 2; projector_y += mwindow->edl->session->output_h / 2; - - float mask_cursor_x = (cursor_x - projector_x) / projector_z + half_track_w; - float mask_cursor_y = (cursor_y - projector_y) / projector_z + half_track_h; + mask_cursor_x = (mask_cursor_x - projector_x) / projector_z + half_track_w; + mask_cursor_y = (mask_cursor_y - projector_y) / projector_z + half_track_h; // Fix cursor origin if(button_press) { @@ -1551,7 +1550,7 @@ int CWindowCanvas::do_mask(int &redraw, int &rerender, y = (y - half_track_h) * projector_z + projector_y; // Test new point addition if(button_press) { - float line_distance = line_dist(x,y, cursor_x,cursor_y); + float line_distance = line_dist(x,y, mask_cursor_x,mask_cursor_y); //printf("CWindowCanvas::do_mask 1 x=%f cursor_x=%f y=%f cursor_y=%f %f %f %d, %d\n", // x, cursor_x, y, cursor_y, line_distance, shortest_line_distance, shortest_point1, shortest_point2); @@ -1571,7 +1570,7 @@ int CWindowCanvas::do_mask(int &redraw, int &rerender, if(gui->shift_down()) { float control_x = (x1 - half_track_w) * projector_z + projector_x; float control_y = (y1 - half_track_h) * projector_z + projector_y; - float distance = line_dist(control_x,control_y, cursor_x,cursor_y); + float distance = line_dist(control_x,control_y, mask_cursor_x,mask_cursor_y); if(distance < selected_control_point_distance) { selected_point = i; @@ -1596,7 +1595,7 @@ int CWindowCanvas::do_mask(int &redraw, int &rerender, if(gui->shift_down()) { float control_x = (x2 - half_track_w) * projector_z + projector_x; float control_y = (y2 - half_track_h) * projector_z + projector_y; - float distance = line_dist(control_x,control_y, cursor_x,cursor_y); + float distance = line_dist(control_x,control_y, mask_cursor_x,mask_cursor_y); //printf("CWindowCanvas::do_mask %d %f %f\n", i, distance, selected_control_point_distance); if(distance < selected_control_point_distance) { @@ -1779,7 +1778,8 @@ int CWindowCanvas::do_mask(int &redraw, int &rerender, //printf("CWindowCanvas::do_mask %d %d\n", shortest_point1, shortest_point2); // Append to end of list - if(labs(shortest_point1 - shortest_point2) > 1) { + if( shortest_point1 == shortest_point2 || + labs(shortest_point1 - shortest_point2) > 1) { #ifdef USE_KEYFRAME_SPANNING MaskPoint *new_point = new MaskPoint; @@ -1865,6 +1865,7 @@ int CWindowCanvas::do_mask(int &redraw, int &rerender, MaskPoint *new_point = new MaskPoint; points.append(new_point); *new_point = *point; + gui->affected_point = points.size() - 1; #else for(MaskAuto *current = (MaskAuto*)mask_autos->default_auto; current; ) { SubMask *submask = current->get_submask(mwindow->edl->session->cwindow_mask); @@ -1876,35 +1877,7 @@ int CWindowCanvas::do_mask(int &redraw, int &rerender, else current = (MaskAuto*)NEXT; } -#endif - -//printf("CWindowCanvas::do_mask 2\n"); -// Create a second point if none existed before -#ifdef USE_KEYFRAME_SPANNING - if(points.size() < 2) { - - MaskPoint *new_point = new MaskPoint; - points.append(new_point); - *new_point = *point; - } - gui->affected_point = points.size() - 1; -#else - if(mask->points.size() < 2) { - - for(MaskAuto *current = (MaskAuto*)mask_autos->default_auto; current; ) { - SubMask *submask = current->get_submask(mwindow->edl->session->cwindow_mask); - MaskPoint *new_point = new MaskPoint; - submask->points.append(new_point); - *new_point = *point; - if(current == (MaskAuto*)mask_autos->default_auto) - current = (MaskAuto*)mask_autos->first; - else - current = (MaskAuto*)NEXT; - } - } - - gui->affected_point = mask->points.size() - 1; #endif //printf("CWindowCanvas::do_mask 3 %d\n", mask->points.size()); @@ -1958,7 +1931,7 @@ int CWindowCanvas::do_mask(int &redraw, int &rerender, //printf("CWindowCanvas::do_mask %d %d\n", __LINE__, gui->affected_point); SubMask *mask = gui->mask_keyframe->get_submask(mwindow->edl->session->cwindow_mask); - if(gui->affected_point < mask->points.size() && + if( gui->affected_point >= 0 && gui->affected_point < mask->points.size() && gui->current_operation != CWINDOW_NONE) { // mwindow->undo->update_undo_before(_("mask point"), this); #ifdef USE_KEYFRAME_SPANNING diff --git a/cinelerra-5.1/cinelerra/cwindowtool.C b/cinelerra-5.1/cinelerra/cwindowtool.C index 4730d81d..64c9f4f3 100644 --- a/cinelerra-5.1/cinelerra/cwindowtool.C +++ b/cinelerra-5.1/cinelerra/cwindowtool.C @@ -1679,6 +1679,7 @@ int CWindowMaskDelete::handle_event() Track *track; MaskPoint *point; SubMask *mask; + int total_points = 0; // Get existing keyframe ((CWindowMaskGUI*)gui)->get_keyframe(track, autos, keyframe, mask, point, 0); @@ -1705,6 +1706,8 @@ int CWindowMaskDelete::handle_event() submask->points.remove_object( submask->points.values[submask->points.total - 1]); } + total_points = submask->points.total; + // Commit change to span of keyframes ((MaskAutos*)track->automation->autos[AUTOMATION_MASK])->update_parameter(&temp_keyframe); #else @@ -1713,8 +1716,6 @@ int CWindowMaskDelete::handle_event() { SubMask *submask = current->get_submask(mwindow->edl->session->cwindow_mask); - - for(int i = mwindow->cwindow->gui->affected_point; i < submask->points.total - 1; i++) @@ -1727,7 +1728,7 @@ int CWindowMaskDelete::handle_event() submask->points.remove_object( submask->points.values[submask->points.total - 1]); } - + total_points = submask->points.total; if(current == (MaskAuto*)autos->default_auto) current = (MaskAuto*)autos->first; @@ -1735,6 +1736,9 @@ int CWindowMaskDelete::handle_event() current = (MaskAuto*)NEXT; } #endif + if( mwindow->cwindow->gui->affected_point >= total_points ) + mwindow->cwindow->gui->affected_point = + total_points > 0 ? total_points-1 : 0; gui->update(); gui->update_preview(); @@ -1860,6 +1864,47 @@ int CWindowMaskNumber::handle_event() } +CWindowMaskAffectedPoint::CWindowMaskAffectedPoint(MWindow *mwindow, + CWindowToolGUI *gui, int x, int y) + : BC_TumbleTextBox(gui, + (int64_t)mwindow->cwindow->gui->affected_point, + (int64_t)0, INT64_MAX, x, y, 100) +{ + this->mwindow = mwindow; + this->gui = gui; +} + +CWindowMaskAffectedPoint::~CWindowMaskAffectedPoint() +{ +} + +int CWindowMaskAffectedPoint::handle_event() +{ + int total_points = 0; + int affected_point = atol(get_text()); + Track *track = mwindow->cwindow->calculate_affected_track(); + if(track) { + MaskAutos *autos = (MaskAutos*)track->automation->autos[AUTOMATION_MASK]; + MaskAuto *keyframe = (MaskAuto*)mwindow->cwindow->calculate_affected_auto(autos, 0); + if( keyframe ) { + SubMask *mask = keyframe->get_submask(mwindow->edl->session->cwindow_mask); + total_points = mask->points.size(); + } + } + int active_point = affected_point; + if( affected_point >= total_points ) + affected_point = total_points - 1; + else if( affected_point < 0 ) + affected_point = 0; + if( active_point != affected_point ) + update((int64_t)affected_point); + mwindow->cwindow->gui->affected_point = affected_point; + gui->update(); + gui->update_preview(); + return 1; +} + + @@ -2016,11 +2061,15 @@ CWindowMaskGUI::CWindowMaskGUI(MWindow *mwindow, CWindowTool *thread) { this->mwindow = mwindow; this->thread = thread; + number = 0; + active_point = 0; + feather = 0; } CWindowMaskGUI::~CWindowMaskGUI() { lock_window("CWindowMaskGUI::~CWindowMaskGUI"); delete number; + delete active_point; delete feather; unlock_window(); } @@ -2044,6 +2093,11 @@ void CWindowMaskGUI::create_objects() add_subwindow(value = new CWindowMaskValue(mwindow, this, x + title->get_w() + margin, y)); y += value->get_h() + margin; add_subwindow(delete_point = new CWindowMaskDelete(mwindow, this, x, y)); + int x1 = x + delete_point->get_w() + 2*margin; + add_subwindow(title = new BC_Title(x1, y, _("Point:"))); + x1 += title->get_w() + margin; + active_point = new CWindowMaskAffectedPoint(mwindow, this, x1, y); + active_point->create_objects(); y += delete_point->get_h() + margin; add_subwindow(title = new BC_Title(x, y, _("Mask number:"))); number = new CWindowMaskNumber(mwindow, @@ -2149,8 +2203,9 @@ void CWindowMaskGUI::update() apply_before_plugins->update((int64_t)keyframe->apply_before_plugins); } } -//printf("CWindowMaskGUI::update 1\n"); +//printf("CWindowMaskGUI::update 1\n"); + active_point->update((int64_t)mwindow->cwindow->gui->affected_point); number->update((int64_t)mwindow->edl->session->cwindow_mask); //printf("CWindowMaskGUI::update 1\n"); diff --git a/cinelerra-5.1/cinelerra/cwindowtool.h b/cinelerra-5.1/cinelerra/cwindowtool.h index 0e6b1a70..2242b2bc 100644 --- a/cinelerra-5.1/cinelerra/cwindowtool.h +++ b/cinelerra-5.1/cinelerra/cwindowtool.h @@ -178,6 +178,18 @@ public: CWindowToolGUI *gui; }; + +class CWindowMaskAffectedPoint : public BC_TumbleTextBox +{ +public: + CWindowMaskAffectedPoint(MWindow *mwindow, CWindowToolGUI *gui, int x, int y); + ~CWindowMaskAffectedPoint(); + int handle_event(); + MWindow *mwindow; + CWindowToolGUI *gui; +}; + + class CWindowMaskFeather : public BC_TumbleTextBox { public: @@ -225,6 +237,7 @@ public: CWindowMaskMode *mode; CWindowMaskFeather *feather; CWindowMaskDelete *delete_point; + CWindowMaskAffectedPoint *active_point; // Not necessary if all keyframes have same points // CWindowMaskCycleNext *next_point; // CWindowMaskCyclePrev *prev_point; diff --git a/cinelerra-5.1/cinelerra/edits.C b/cinelerra-5.1/cinelerra/edits.C index 1c12dc34..7d152bc5 100644 --- a/cinelerra-5.1/cinelerra/edits.C +++ b/cinelerra-5.1/cinelerra/edits.C @@ -234,72 +234,33 @@ Edit* Edits::insert_new_edit(int64_t position) return new_edit; } - Edit* Edits::split_edit(int64_t position) { // Get edit containing position Edit *edit = editof(position, PLAY_FORWARD, 0); -// No edit found, make one - except when we are at zero position! - if(!edit && position != 0) { - if (length() == position) { - edit = last; // we do not need any edit to extend past the last one - } - else if (!last || length() < position) { - - // Even when track is completely empty or split is beyond last edit, return correct edit - Edit *empty = create_edit(); - if (last) - empty->startproject = length(); // end of last edit - else - empty->startproject = 0; // empty track - empty->length = position - empty->startproject; - insert_after(last, empty); - edit = empty; - } - else { - // now we are now surely in situation where we have - // a) broken edit list or b) negative position... report error! - printf("ERROR!\n"); - printf("Trying to insert edit at position, but failed: %ji\n", position); - printf("Dump is here:\n"); - track->dump(stdout); - return 0; - } - } if(!edit) return 0; - return split_edit(edit, position); -} - -Edit* Edits::split_edit(Edit *edit, int64_t position) -{ // Split would have created a 0 length // if(edit->startproject == position) return edit; // Create anyway so the return value comes before position Edit *new_edit = create_edit(); insert_after(edit, new_edit); - if (edit) // if we have actually split the edit, do the funky stuff! - { - new_edit->copy_from(edit); - new_edit->length = new_edit->startproject + new_edit->length - position; - edit->length = position - edit->startproject; - new_edit->startsource += edit->length; - + new_edit->copy_from(edit); + new_edit->length = new_edit->startproject + new_edit->length - position; + edit->length = position - edit->startproject; + new_edit->startproject = position; + new_edit->startsource += edit->length; // Decide what to do with the transition - if(edit->length && edit->transition) - { - delete new_edit->transition; - new_edit->transition = 0; - } + if(edit->length && edit->transition) { + delete new_edit->transition; + new_edit->transition = 0; + } - if(edit->transition && edit->transition->length > edit->length) - edit->transition->length = edit->length; - if(new_edit->transition && new_edit->transition->length > new_edit->length) - new_edit->transition->length = new_edit->length; - } else - new_edit->length = 0; - new_edit->startproject = position; + if(edit->transition && edit->transition->length > edit->length) + edit->transition->length = edit->length; + if(new_edit->transition && new_edit->transition->length > new_edit->length) + new_edit->transition->length = new_edit->length; return new_edit; } @@ -403,11 +364,10 @@ int Edits::optimize() result = 0; // delete 0 length edits - for(current = first; !result && current; ) { + for( current = first; !result && current; ) { Edit* next = current->next; - if(current->length == 0) { - // Be smart with transitions! - if (next && current->transition && !next->transition) { + if( current->length == 0 ) { + if( next && current->transition && !next->transition) { next->transition = current->transition; next->transition->edit = next; current->transition = 0; @@ -431,10 +391,8 @@ int Edits::optimize() // current->channel, next_edit->channel, current->asset, next_edit->asset, // current->nested_edl, next_edit->nested_edl); - // both edits are silence & not a plugin -// source channels are identical -// assets are identical +// source channels are identical, assets are identical if( (current->silence() && next_edit->silence() && !current->is_plugin) || (current->startsource + current->length == next_edit->startsource && current->channel == next_edit->channel && @@ -444,7 +402,7 @@ int Edits::optimize() current->length += next_edit->length; remove(next_edit); result = 1; - continue; + break; } current = current->next; @@ -471,8 +429,7 @@ void Edits::load(FileXML *file, int track_offset) while( !file->read_tag() ) { //printf("Edits::load 1 %s\n", file->tag.get_title()); - if(!strcmp(file->tag.get_title(), "EDIT")) - { + if(!strcmp(file->tag.get_title(), "EDIT")) { load_edit(file, startproject, track_offset); } else if(!strcmp(file->tag.get_title(), "/EDITS")) @@ -487,51 +444,45 @@ int Edits::load_edit(FileXML *file, int64_t &startproject, int track_offset) { Edit* current = append_new_edit(); current->load_properties(file, startproject); + startproject += current->length; while( !file->read_tag() ) { - if(file->tag.title_is("NESTED_EDL")) - { + if(file->tag.title_is("NESTED_EDL")) { char path[BCTEXTLEN]; path[0] = 0; file->tag.get_property("SRC", path); //printf("Edits::load_edit %d path=%s\n", __LINE__, path); - if(path[0] != 0) - { + if(path[0] != 0) { current->nested_edl = edl->nested_edls->get(path); } // printf("Edits::load_edit %d nested_edl->path=%s\n", // __LINE__, // current->nested_edl->path); } - else if(file->tag.title_is("FILE")) - { + else if(file->tag.title_is("FILE")) { char filename[BCTEXTLEN]; filename[0] = 0; file->tag.get_property("SRC", filename); // Extend path - if(filename[0] != 0) - { + if(filename[0] != 0) { char directory[BCTEXTLEN], edl_directory[BCTEXTLEN]; FileSystem fs; fs.set_current_dir(""); fs.extract_dir(directory, filename); - if(!strlen(directory)) - { + if(!strlen(directory)) { fs.extract_dir(edl_directory, file->filename); fs.join_names(directory, edl_directory, filename); strcpy(filename, directory); } current->asset = edl->assets->get_asset(filename); } - else - { + else { current->asset = 0; } //printf("Edits::load_edit 5\n"); } - else if(file->tag.title_is("TRANSITION")) - { + else if(file->tag.title_is("TRANSITION")) { current->transition = new Transition(edl, current, "", track->to_units(edl->session->default_transition_length, 1)); current->transition->load_xml(file); @@ -560,19 +511,15 @@ Edit* Edits::editof(int64_t position, int direction, int use_nudge) Edit *current = 0; if(use_nudge && track) position += track->nudge; - if(direction == PLAY_FORWARD) - { - for(current = last; current; current = PREVIOUS) - { + if(direction == PLAY_FORWARD) { + for(current = last; current; current = PREVIOUS) { if(current->startproject <= position && current->startproject + current->length > position) return current; } } else - if(direction == PLAY_REVERSE) - { - for(current = first; current; current = NEXT) - { + if(direction == PLAY_REVERSE) { + for(current = first; current; current = NEXT) { if(current->startproject < position && current->startproject + current->length >= position) return current; } @@ -587,8 +534,7 @@ Edit* Edits::get_playable_edit(int64_t position, int use_nudge) if(track && use_nudge) position += track->nudge; // Get the current edit - for(current = first; current; current = NEXT) - { + for(current = first; current; current = NEXT) { if(current->startproject <= position && current->startproject + current->length > position) break; @@ -596,8 +542,7 @@ Edit* Edits::get_playable_edit(int64_t position, int use_nudge) // Get the edit's asset // TODO: descend into nested EDLs - if(current) - { + if(current) { if(!current->asset) current = 0; } @@ -638,11 +583,11 @@ void Edits::clear(int64_t start, int64_t end) Edit* edit2 = editof(end, PLAY_FORWARD, 0); Edit* current_edit; + if(end == start) return; // nothing selected if(!edit1 && !edit2) return; // nothing selected - if(!edit2) - { // edit2 beyond end of track + if(!edit2) { // edit2 beyond end of track edit2 = last; end = this->length(); } @@ -658,33 +603,27 @@ void Edits::clear(int64_t start, int64_t end) edit2->startproject += end - edit2->startproject; // delete - for(current_edit = edit1->next; current_edit && current_edit != edit2;) - { + for(current_edit = edit1->next; current_edit && current_edit != edit2;) { Edit* next = current_edit->next; remove(current_edit); current_edit = next; } // shift - for(current_edit = edit2; current_edit; current_edit = current_edit->next) - { + for(current_edit = edit2; current_edit; current_edit = current_edit->next) { current_edit->startproject -= end - start; } } - else - { + else { // in same edit. paste_edit depends on this // create a new edit current_edit = split_edit(start); - - current_edit->length -= end - start; - current_edit->startsource += end - start; - + if( current_edit ) { + current_edit->length -= end - start; + current_edit->startsource += end - start; // shift - for(current_edit = current_edit->next; - current_edit; - current_edit = current_edit->next) - { - current_edit->startproject -= end - start; + while( (current_edit=current_edit->next) != 0 ) { + current_edit->startproject -= end - start; + } } } @@ -693,55 +632,37 @@ void Edits::clear(int64_t start, int64_t end) // Used by edit handle and plugin handle movement but plugin handle movement // can only effect other plugins. -void Edits::clear_recursive(int64_t start, - int64_t end, - int edit_edits, - int edit_labels, - int edit_plugins, - int edit_autos, +void Edits::clear_recursive(int64_t start, int64_t end, + int edit_edits, int edit_labels, int edit_plugins, int edit_autos, Edits *trim_edits) { //printf("Edits::clear_recursive 1\n"); - track->clear(start, - end, - edit_edits, - edit_labels, - edit_plugins, - edit_autos, - 0, + track->clear(start, end, + edit_edits, edit_labels, edit_plugins, edit_autos, 0, trim_edits); } -int Edits::clear_handle(double start, - double end, - int edit_plugins, - int edit_autos, - double &distance) +int Edits::clear_handle(double start, double end, + int edit_plugins, int edit_autos, double &distance) { Edit *current_edit; distance = 0.0; // if nothing is found, distance is 0! for(current_edit = first; current_edit && current_edit->next; - current_edit = current_edit->next) - { + current_edit = current_edit->next) { - if(current_edit->asset && - current_edit->next->asset) - { + if(current_edit->asset && current_edit->next->asset) { if(current_edit->asset->equivalent(*current_edit->next->asset, - 0, - 0)) - { + 0, 0)) { // Got two consecutive edits in same source if(edl->equivalent(track->from_units(current_edit->next->startproject), - start)) - { + start)) { // handle selected int length = -current_edit->length; current_edit->length = current_edit->next->startsource - current_edit->startsource; @@ -774,35 +695,25 @@ int Edits::clear_handle(double start, return 0; } -int Edits::modify_handles(double oldposition, - double newposition, - int currentend, - int edit_mode, - int edit_edits, - int edit_labels, - int edit_plugins, - int edit_autos, +int Edits::modify_handles(double oldposition, double newposition, int currentend, + int edit_mode, int edit_edits, int edit_labels, int edit_plugins, int edit_autos, Edits *trim_edits) { int result = 0; Edit *current_edit; //printf("Edits::modify_handles 1 %d %f %f\n", currentend, newposition, oldposition); - if(currentend == 0) - { + if(currentend == 0) { // left handle - for(current_edit = first; current_edit && !result;) - { + for(current_edit = first; current_edit && !result;) { if(edl->equivalent(track->from_units(current_edit->startproject), - oldposition)) - { + oldposition)) { // edit matches selection //printf("Edits::modify_handles 3 %f %f\n", newposition, oldposition); oldposition = track->from_units(current_edit->startproject); result = 1; - if(newposition >= oldposition) - { + if(newposition >= oldposition) { //printf("Edits::modify_handle 1 %s %f %f\n", track->title, oldposition, newposition); // shift start of edit in current_edit->shift_start_in(edit_mode, @@ -832,21 +743,17 @@ int Edits::modify_handles(double oldposition, if(!result) current_edit = current_edit->next; } } - else - { + else { // right handle selected - for(current_edit = first; current_edit && !result;) - { + for(current_edit = first; current_edit && !result;) { if(edl->equivalent(track->from_units(current_edit->startproject) + - track->from_units(current_edit->length), oldposition)) - { + track->from_units(current_edit->length), oldposition)) { oldposition = track->from_units(current_edit->startproject) + track->from_units(current_edit->length); result = 1; //printf("Edits::modify_handle 3\n"); - if(newposition <= oldposition) - { + if(newposition <= oldposition) { // shift end of edit in //printf("Edits::modify_handle 4\n"); current_edit->shift_end_in(edit_mode, @@ -887,25 +794,20 @@ int Edits::modify_handles(double oldposition, void Edits::paste_silence(int64_t start, int64_t end) { - // paste silence does not do anything if - // a) paste silence is on empty track - // b) paste silence is after last edit - // in both cases editof returns NULL Edit *new_edit = editof(start, PLAY_FORWARD, 0); if (!new_edit) return; - if (!new_edit->asset) - { // in this case we extend already existing edit - new_edit->length += end - start; - } else - { // we are in fact creating a new edit + if( !new_edit->silence() ) { new_edit = insert_new_edit(start); new_edit->length = end - start; } - for(Edit *current = new_edit->next; current; current = NEXT) - { + else + new_edit->length += end - start; + + for(Edit *current = new_edit->next; current; current = NEXT) { current->startproject += end - start; } + return; } @@ -913,23 +815,18 @@ Edit *Edits::create_silence(int64_t start, int64_t end) { Edit *new_edit = insert_new_edit(start); new_edit->length = end - start; - for(Edit *current = new_edit->next; current; current = NEXT) - { + for(Edit *current = new_edit->next; current; current = NEXT) { current->startproject += end - start; } return new_edit; } - + Edit* Edits::shift(int64_t position, int64_t difference) { Edit *new_edit = split_edit(position); - for(Edit *current = first; - current; - current = NEXT) - { - if(current->startproject >= position) - { + for(Edit *current = first; current; current = NEXT) { + if(current->startproject >= position) { current->shift(difference); } } diff --git a/cinelerra-5.1/cinelerra/edits.h b/cinelerra-5.1/cinelerra/edits.h index cd1c61e7..d35917c7 100644 --- a/cinelerra-5.1/cinelerra/edits.h +++ b/cinelerra-5.1/cinelerra/edits.h @@ -56,9 +56,8 @@ public: int64_t sample, int track_number); // Split edit containing position. - Edit* split_edit(int64_t position); // Return the second edit in the split. - Edit* split_edit(Edit *edit, int64_t position); + Edit* split_edit(int64_t position); // Create a blank edit in the native data format int clear_handle(double start, double end, diff --git a/cinelerra-5.1/cinelerra/edlsession.h b/cinelerra-5.1/cinelerra/edlsession.h index bf0acbb9..9affcfef 100644 --- a/cinelerra-5.1/cinelerra/edlsession.h +++ b/cinelerra-5.1/cinelerra/edlsession.h @@ -22,6 +22,7 @@ #ifndef EDLSESSION_H #define EDLSESSION_H +#include "asset.inc" #include "autoconf.inc" #include "bcwindowbase.inc" #include "bchash.inc" diff --git a/cinelerra-5.1/cinelerra/maskengine.C b/cinelerra-5.1/cinelerra/maskengine.C index 9f2861fe..a8fd4acf 100644 --- a/cinelerra-5.1/cinelerra/maskengine.C +++ b/cinelerra-5.1/cinelerra/maskengine.C @@ -63,77 +63,6 @@ MaskUnit::~MaskUnit() #define OVERSAMPLE 8 -#if 1 -// Bresenham's -void MaskUnit::draw_line_clamped(VFrame *frame, - int x1,int y1, int x2,int y2, unsigned char k) -{ - int w = frame->get_w(), h = frame->get_h(); - unsigned char **rows = (unsigned char**)frame->get_rows(); - int dx = x2-x1, dy = y2-y1; -//printf("MaskUnit::draw_line_clamped(%d,%d -> %d,%d, 0x%02x\n", x1,y1, x2,y2, k); - - int ax = 2*abs(dx), ay = 2*abs(dy); - - if( ax > ay ) { /* x dominant */ - if( dx == 0 ) return; - if( x1 > x2 ) { - int xx = x2; x2 = x1; x1 = xx; - int yy = y2; y2 = y1; y1 = yy; - } - if( x1 >= w || x2 < 0 ) return; - if( dx < 0 ) { dx = -dx; dy = -dy; } - int x = x1, y = y1, d = dx; - int sy = dy < 0 ? -1 : 1; - if( x1 < 0 ) { - double py = -(double)dy/dx * x1 + y1 + 0.5; - x = 0; y = py; - d = (py - y) * ay; - } - - for( int y0=-1;;) { - if( x >= w ) return; - if( y != y0 && y >= 0 && y < h ) { - y0 = y; - unsigned char *bp = rows[y] + x; - *bp = *bp == k ? 0 : k; - } - if( x == x2 ) return; - if( d < 0 ) { d += ax; y += sy; } - d -= ay; ++x; - } - } - else { /* y dominant */ - if( dy == 0 ) return; - if( y1 > y2 ) { - int xx = x2; x2 = x1; x1 = xx; - int yy = y2; y2 = y1; y1 = yy; - } - if( y1 >= h || y2 < 0 ) return; - if( dy < 0 ) { dx = -dx; dy = -dy; } - int x = x1, y = y1, d = dy; - int sx = dx < 0 ? -1 : 1; - if( y1 < 0 ) { - double px = -(double)dx/dy * y1 + x1 + 0.5; - x = px; y = 0; - d = (px - x) * ax; - } - - for(;;) { - if( y >= h ) return; - if( x >= 0 && x < w ) { - unsigned char *bp = rows[y] + x; - *bp = *bp == k ? 0 : k; - } - if( y == y2 ) return; - if( d < 0 ) { d += ay; x += sx; } - d -= ax; ++y; - } - } -} - -#else - void MaskUnit::draw_line_clamped(VFrame *frame, int x1, int y1, int x2, int y2, unsigned char k) { @@ -171,8 +100,6 @@ void MaskUnit::draw_line_clamped(VFrame *frame, } } -#endif - void MaskUnit::blur_strip(double *val_p, double *val_m, double *dst, diff --git a/cinelerra-5.1/cinelerra/playback3d.C b/cinelerra-5.1/cinelerra/playback3d.C index a6a721ba..35f4fd0e 100644 --- a/cinelerra-5.1/cinelerra/playback3d.C +++ b/cinelerra-5.1/cinelerra/playback3d.C @@ -197,10 +197,10 @@ static const char *blend_divide_frag = "void main() {\n" " vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" " vec4 result = gl_FragColor / canvas;\n" - " if(!canvas.r) result.r = 1.0;\n" - " if(!canvas.g) result.g = 1.0;\n" - " if(!canvas.b) result.b = 1.0;\n" - " if(!canvas.a) result.a = 1.0;\n" + " if(canvas.r == 0.) result.r = 1.0;\n" + " if(canvas.g == 0.) result.g = 1.0;\n" + " if(canvas.b == 0.) result.b = 1.0;\n" + " if(canvas.a == 0.) result.a = 1.0;\n" " result = clamp(result, 0.0, 1.0);\n" " gl_FragColor = mix(canvas, result, alpha);\n" "}\n"; @@ -219,7 +219,6 @@ static const char *blend_max_frag = "void main() {\n" " vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" " vec4 result = max(canvas, gl_FragColor);\n" - " result = clamp(result, 0.0, 1.0);\n" " gl_FragColor = mix(canvas, result, alpha);\n" "}\n"; @@ -231,7 +230,6 @@ static const char *blend_min_frag = "void main() {\n" " vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" " vec4 result = min(canvas, gl_FragColor);\n" - " result = clamp(result, 0.0, 1.0);\n" " gl_FragColor = mix(canvas, result, alpha);\n" "}\n"; @@ -243,7 +241,6 @@ static const char *blend_average_frag = "void main() {\n" " vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" " vec4 result = (canvas + gl_FragColor) * 0.5;\n" - " result = clamp(result, 0.0, 1.0);\n" " gl_FragColor = mix(canvas, result, alpha);\n" "}\n"; @@ -400,7 +397,6 @@ static const char *blend_or_frag = "void main() {\n" " vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" " vec4 result = canvas + gl_FragColor - canvas * gl_FragColor;\n" - " result = clamp(result, 0.0, 1.0);\n" " gl_FragColor = mix(canvas, result, alpha);\n" "}\n"; @@ -739,7 +735,7 @@ void Playback3D::copy_from_sync(Playback3DCommand *command) // command->frame->get_h(), // BC_RGB888, // -1); -// command->frame->to_ram(); +// command->frame->screen_to_ram(); // // window->clear_box(0, // 0, diff --git a/cinelerra-5.1/cinelerra/vwindowgui.C b/cinelerra-5.1/cinelerra/vwindowgui.C index 6bd71b1f..7fcd82a2 100644 --- a/cinelerra-5.1/cinelerra/vwindowgui.C +++ b/cinelerra-5.1/cinelerra/vwindowgui.C @@ -635,7 +635,7 @@ double VWindowEditing::get_position() void VWindowEditing::set_position(double position) { EDL *edl = vwindow->get_edl(); - if( edl ) return; + if( !edl ) return; if( get_position() != position ) { position -= edl->session->get_frame_offset() / edl->session->frame_rate; if( position < 0 ) position = 0; diff --git a/cinelerra-5.1/guicast/bcpopupmenu.C b/cinelerra-5.1/guicast/bcpopupmenu.C index beabdd3d..cefaea7f 100644 --- a/cinelerra-5.1/guicast/bcpopupmenu.C +++ b/cinelerra-5.1/guicast/bcpopupmenu.C @@ -418,7 +418,10 @@ int BC_PopupMenu::button_release_event() } } - if(popup_down) + if( !use_title && status == BUTTON_DN ) { + result = 1; + } + else if(popup_down) { // Menu is down so dispatch to popup. result = menu_popup->dispatch_button_release(); diff --git a/cinelerra-5.1/guicast/vframe.C b/cinelerra-5.1/guicast/vframe.C index 1eec314b..7f57329b 100644 --- a/cinelerra-5.1/guicast/vframe.C +++ b/cinelerra-5.1/guicast/vframe.C @@ -790,6 +790,11 @@ int VFrame::write_png(const char *path) png_cmodel = PNG_COLOR_TYPE_RGB; break; + case BC_RGBA8888: + case BC_YUVA8888: + png_cmodel = PNG_COLOR_TYPE_RGB_ALPHA; + break; + case BC_A8: png_cmodel = PNG_COLOR_TYPE_GRAY; break; diff --git a/cinelerra-5.1/guicast/vframe.h b/cinelerra-5.1/guicast/vframe.h index 57596891..f0d88777 100644 --- a/cinelerra-5.1/guicast/vframe.h +++ b/cinelerra-5.1/guicast/vframe.h @@ -213,8 +213,9 @@ public: // Must be called from a synchronous opengl thread after enable_opengl. void to_texture(); -// Transfer from PBuffer to RAM. Only used after Playback3D::overlay_sync - void to_ram(); +// Transfer from PBuffer to RAM. +// used in Playback3D::overlay_sync, plugin Overlay::handle_opengl + void screen_to_ram(); // Transfer contents of current pbuffer to texture, // creating a new texture if necessary. diff --git a/cinelerra-5.1/guicast/vframe3d.C b/cinelerra-5.1/guicast/vframe3d.C index 3ed62aca..f6f0a440 100644 --- a/cinelerra-5.1/guicast/vframe3d.C +++ b/cinelerra-5.1/guicast/vframe3d.C @@ -152,33 +152,6 @@ void VFrame::to_texture() #endif } -void VFrame::to_ram() -{ -#ifdef HAVE_GL - switch(opengl_state) - { -// Only pbuffer is supported since this is only called after the -// overlay operation onto the pbuffer. - case VFrame::SCREEN: - if(pbuffer) - { - enable_opengl(); -//printf("VFrame::to_ram %d %d\n", get_w(), get_h()); - glReadPixels(0, - 0, - get_w(), - get_h(), - GL_RGB, - GL_UNSIGNED_BYTE, - get_rows()[0]); - flip_vert(); - } - opengl_state = VFrame::RAM; - return; - } -#endif -} - void VFrame::create_pbuffer() { if(pbuffer && @@ -220,12 +193,9 @@ void VFrame::screen_to_texture(int x, int y, int w, int h) #ifdef HAVE_GL // Create texture BC_Texture::new_texture(&texture, - get_w(), - get_h(), - get_color_model()); + get_w(), get_h(), get_color_model()); - if(pbuffer) - { + if(pbuffer) { glEnable(GL_TEXTURE_2D); // Read canvas into texture, use back texture for DOUBLE_BUFFER @@ -247,6 +217,18 @@ void VFrame::screen_to_texture(int x, int y, int w, int h) #endif } +void VFrame::screen_to_ram() +{ +#ifdef HAVE_GL + enable_opengl(); + glReadBuffer(GL_BACK); + int type = BC_CModels::is_float(color_model) ? GL_FLOAT : GL_UNSIGNED_BYTE; + int format = BC_CModels::has_alpha(color_model) ? GL_RGBA : GL_RGB; + glReadPixels(0, 0, get_w(), get_h(), format, type, get_rows()[0]); + opengl_state = VFrame::RAM; +#endif +} + void VFrame::draw_texture(float in_x1, float in_y1, float in_x2, diff --git a/cinelerra-5.1/plugins/overlay/overlay.C b/cinelerra-5.1/plugins/overlay/overlay.C index d3bdd92c..e1ca0961 100644 --- a/cinelerra-5.1/plugins/overlay/overlay.C +++ b/cinelerra-5.1/plugins/overlay/overlay.C @@ -22,6 +22,7 @@ #include "bcdisplayinfo.h" #include "clip.h" #include "bchash.h" +#include "edlsession.h" #include "filexml.h" #include "guicast.h" #include "keyframe.h" @@ -136,9 +137,7 @@ public: VFrame *temp; int current_layer; int output_layer; -// Inclusive layer numbers - int input_layer1; - int input_layer2; + int input_layer; }; OverlayConfig::OverlayConfig() @@ -419,93 +418,44 @@ int Overlay::process_buffer(VFrame **frame, { load_configuration(); - - if(!temp) temp = new VFrame(0, - -1, - frame[0]->get_w(), - frame[0]->get_h(), - frame[0]->get_color_model(), - -1); - - if(!overlayer) - overlayer = new OverlayFrame(get_project_smp() + 1); - - int step; - VFrame *output; - - if(config.direction == OverlayConfig::BOTTOM_FIRST) - { - input_layer1 = get_total_buffers() - 1; - input_layer2 = -1; - step = -1; - } - else - { - input_layer1 = 0; - input_layer2 = get_total_buffers(); - step = 1; - } - - if(config.output_layer == OverlayConfig::TOP) - { - output_layer = 0; - } - else - { - output_layer = get_total_buffers() - 1; - } - - - -// Direct copy the first layer - output = frame[output_layer]; - read_frame(output, - input_layer1, - start_position, - frame_rate, - get_use_opengl()); - - if(get_total_buffers() == 1) return 0; - - - - current_layer = input_layer1; - if(get_use_opengl()) - run_opengl(); - - for(int i = input_layer1 + step; i != input_layer2; i += step) - { - read_frame(temp, - i, - start_position, - frame_rate, - get_use_opengl()); - -// Call the opengl handler once for each layer - if(get_use_opengl()) - { - current_layer = i; - run_opengl(); - } - else - { - overlayer->overlay(output, - temp, - 0, - 0, - output->get_w(), - output->get_h(), - 0, - 0, - output->get_w(), - output->get_h(), - 1, - config.mode, - NEAREST_NEIGHBOR); + EDLSession* session = get_edlsession(); + int interpolation_type = session ? session->interpolation_type : NEAREST_NEIGHBOR; + + int step = config.direction == OverlayConfig::BOTTOM_FIRST ? -1 : 1; + int layers = get_total_buffers(); + input_layer = config.direction == OverlayConfig::BOTTOM_FIRST ? layers-1 : 0; + output_layer = config.output_layer == OverlayConfig::TOP ? 0 : layers-1; + VFrame *output = frame[output_layer]; + + current_layer = input_layer; + read_frame(output, current_layer, // Direct copy the first layer + start_position, frame_rate, get_use_opengl()); + + if( --layers > 0 ) { // need 2 layers to do overlay + if( !temp ) + temp = new VFrame(0, -1, frame[0]->get_w(), frame[0]->get_h(), + frame[0]->get_color_model(), -1); + + while( --layers >= 0 ) { + current_layer += step; + read_frame(temp, current_layer, + start_position, frame_rate, get_use_opengl()); + + if(get_use_opengl()) { + run_opengl(); + continue; + } + + if(!overlayer) + overlayer = new OverlayFrame(get_project_smp() + 1); + + overlayer->overlay(output, temp, + 0, 0, output->get_w(), output->get_h(), + 0, 0, output->get_w(), output->get_h(), + 1, config.mode, interpolation_type); } } - return 0; } @@ -519,132 +469,192 @@ int Overlay::handle_opengl() "uniform vec3 chroma_offset;\n" "void main()\n" "{\n" - " vec4 result_color;\n" " vec4 dst_color = texture2D(dst_tex, gl_FragCoord.xy / dst_tex_dimensions);\n" " vec4 src_color = texture2D(src_tex, gl_TexCoord[0].st);\n" " src_color.rgb -= chroma_offset;\n" " dst_color.rgb -= chroma_offset;\n"; static const char *put_pixels_frag = - " result_color.rgb += chroma_offset;\n" - " result_color.rgb = mix(dst_color.rgb, result_color.rgb, src_color.a);\n" - " result_color.a = max(src_color.a, dst_color.a);\n" - " gl_FragColor = result_color;\n" + " result.rgb += chroma_offset;\n" + " gl_FragColor = result;\n" "}\n"; - static const char *blend_add_frag = - " result_color.rgb = dst_color.rgb + src_color.rgb;\n"; - - static const char *blend_max_frag = - " result_color.r = max(abs(dst_color.r, src_color.r);\n" - " result_color.g = max(abs(dst_color.g, src_color.g);\n" - " result_color.b = max(abs(dst_color.b, src_color.b);\n"; - - static const char *blend_min_frag = - " result_color.r = min(abs(dst_color.r, src_color.r);\n" - " result_color.g = min(abs(dst_color.g, src_color.g);\n" - " result_color.b = min(abs(dst_color.b, src_color.b);\n"; - - static const char *blend_subtract_frag = - " result_color.rgb = dst_color.rgb - src_color.rgb;\n"; - - - static const char *blend_multiply_frag = - " result_color.rgb = dst_color.rgb * src_color.rgb;\n"; - - static const char *blend_divide_frag = - " result_color.rgb = dst_color.rgb / src_color.rgb;\n" - " if(src_color.r == 0.0) result_color.r = 1.0;\n" - " if(src_color.g == 0.0) result_color.g = 1.0;\n" - " if(src_color.b == 0.0) result_color.b = 1.0;\n"; +// NORMAL +static const char *blend_normal_frag = + " vec4 result = mix(src_color, src_color, src_color.a);\n"; + +// ADDITION +static const char *blend_add_frag = + " vec4 result = dst_color + src_color;\n" + " result = clamp(result, 0.0, 1.0);\n"; + +// SUBTRACT +static const char *blend_subtract_frag = + " vec4 result = dst_color - src_color;\n" + " result = clamp(result, 0.0, 1.0);\n"; + +// MULTIPLY +static const char *blend_multiply_frag = + " vec4 result = dst_color * src_color;\n"; + +// DIVIDE +static const char *blend_divide_frag = + " vec4 result = dst_color / src_color;\n" + " if(src_color.r == 0.) result.r = 1.0;\n" + " if(src_color.g == 0.) result.g = 1.0;\n" + " if(src_color.b == 0.) result.b = 1.0;\n" + " if(src_color.a == 0.) result.a = 1.0;\n" + " result = clamp(result, 0.0, 1.0);\n"; + +// MAX +static const char *blend_max_frag = + " vec4 result = max(src_color, dst_color);\n"; + +// MIN +static const char *blend_min_frag = + " vec4 result = min(src_color, dst_color);\n"; + +// AVERAGE +static const char *blend_average_frag = + " vec4 result = (src_color + dst_color) * 0.5;\n"; + +// DARKEN +static const char *blend_darken_frag = + " vec4 result = vec4(src_color.rgb * (1.0 - dst_color.a) +" + " dst_color.rgb * (1.0 - src_color.a) +" + " min(src_color.rgb, dst_color.rgb), " + " src_color.a + dst_color.a - src_color.a * dst_color.a);\n" + " result = clamp(result, 0.0, 1.0);\n"; + +// LIGHTEN +static const char *blend_lighten_frag = + " vec4 result = vec4(src_color.rgb * (1.0 - dst_color.a) +" + " dst_color.rgb * (1.0 - src_color.a) +" + " max(src_color.rgb, dst_color.rgb), " + " src_color.a + dst_color.a - src_color.a * dst_color.a);\n" + " result = clamp(result, 0.0, 1.0);\n"; + +// DST +static const char *blend_dst_frag = + " vec4 result = dst_color;\n"; + +// DST_ATOP +static const char *blend_dst_atop_frag = + " vec4 result = vec4(src_color.rgb * dst_color.a + " + "(1.0 - src_color.a) * dst_color.rgb, dst_color.a);\n"; + +// DST_IN +static const char *blend_dst_in_frag = + " vec4 result = src_color * dst_color.a;\n"; + +// DST_OUT +static const char *blend_dst_out_frag = + " vec4 result = src_color * (1.0 - dst_color.a);\n"; + +// DST_OVER +static const char *blend_dst_over_frag = + " vec4 result = vec4(src_color.rgb + (1.0 - src_color.a) * dst_color.rgb, " + " dst_color.a + src_color.a - dst_color.a * src_color.a);\n"; + +// SRC +static const char *blend_src_frag = + " vec4 result = src_color;\n"; + +// SRC_ATOP +static const char *blend_src_atop_frag = + " vec4 result = vec4(dst_color.rgb * src_color.a + " + "src_color.rgb * (1.0 - dst_color.a), src_color.a);\n"; + +// SRC_IN +static const char *blend_src_in_frag = + " vec4 result = dst_color * src_color.a;\n"; + +// SRC_OUT +static const char *blend_src_out_frag = + " vec4 result = dst_color * (1.0 - src_color.a);\n"; + +// SRC_OVER +static const char *blend_src_over_frag = + " vec4 result = vec4(dst_color.rgb + (1.0 - dst_color.a) * src_color.rgb, " + "dst_color.a + src_color.a - dst_color.a * src_color.a);\n"; + +// OR +static const char *blend_or_frag = + " vec4 result = src_color + dst_color - src_color * dst_color;\n"; + +// XOR +static const char *blend_xor_frag = + " vec4 result = vec4(dst_color.rgb * (1.0 - src_color.a) + " + "(1.0 - dst_color.a) * src_color.rgb, " + "dst_color.a + src_color.a - 2.0 * dst_color.a * src_color.a);\n"; + +static const char * const overlay_shaders[TRANSFER_TYPES] = { + blend_normal_frag, // TRANSFER_NORMAL + blend_add_frag, // TRANSFER_ADDITION + blend_subtract_frag, // TRANSFER_SUBTRACT + blend_multiply_frag, // TRANSFER_MULTIPLY + blend_divide_frag, // TRANSFER_DIVIDE + blend_src_frag, // TRANSFER_REPLACE + blend_max_frag, // TRANSFER_MAX + blend_min_frag, // TRANSFER_MIN + blend_average_frag, // TRANSFER_AVERAGE + blend_darken_frag, // TRANSFER_DARKEN + blend_lighten_frag, // TRANSFER_LIGHTEN + blend_dst_frag, // TRANSFER_DST + blend_dst_atop_frag, // TRANSFER_DST_ATOP + blend_dst_in_frag, // TRANSFER_DST_IN + blend_dst_out_frag, // TRANSFER_DST_OUT + blend_dst_over_frag, // TRANSFER_DST_OVER + blend_src_frag, // TRANSFER_SRC + blend_src_atop_frag, // TRANSFER_SRC_ATOP + blend_src_in_frag, // TRANSFER_SRC_IN + blend_src_out_frag, // TRANSFER_SRC_OUT + blend_src_over_frag, // TRANSFER_SRC_OVER + blend_or_frag, // TRANSFER_OR + blend_xor_frag // TRANSFER_XOR + }; - VFrame *src = temp; + glDisable(GL_BLEND); VFrame *dst = get_output(output_layer); + VFrame *src = temp; - dst->enable_opengl(); - dst->init_screen(); - - const char *shader_stack[] = { 0, 0, 0 }; - int current_shader = 0; - - - - + switch( config.mode ) { + case TRANSFER_REPLACE: + case TRANSFER_SRC: // Direct copy layer - if(config.mode == TRANSFER_REPLACE) - { - src->to_texture(); - src->bind_texture(0); - dst->enable_opengl(); + src->to_texture(); + dst->enable_opengl(); dst->init_screen(); - -// Multiply alpha - glDisable(GL_BLEND); src->draw_texture(); - } - else - if(config.mode == TRANSFER_NORMAL) - { - dst->enable_opengl(); - dst->init_screen(); - + break; + case TRANSFER_NORMAL: // Move destination to screen - if(dst->get_opengl_state() != VFrame::SCREEN) - { + if( dst->get_opengl_state() != VFrame::SCREEN ) { dst->to_texture(); - dst->bind_texture(0); + dst->enable_opengl(); + dst->init_screen(); dst->draw_texture(); } - - src->to_texture(); - src->bind_texture(0); - dst->enable_opengl(); + src->to_texture(); + dst->enable_opengl(); dst->init_screen(); - glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); src->draw_texture(); - } - else - { -// Read destination back to texture + break; + default: + src->to_texture(); dst->to_texture(); - - src->enable_opengl(); - src->init_screen(); - src->to_texture(); - - dst->enable_opengl(); + dst->enable_opengl(); dst->init_screen(); - src->bind_texture(0); - dst->bind_texture(1); - + src->bind_texture(0); + dst->bind_texture(1); + const char *shader_stack[] = { 0, 0, 0 }; + int current_shader = 0; shader_stack[current_shader++] = get_pixels_frag; - - switch(config.mode) - { - case TRANSFER_ADDITION: - shader_stack[current_shader++] = blend_add_frag; - break; - case TRANSFER_SUBTRACT: - shader_stack[current_shader++] = blend_subtract_frag; - break; - case TRANSFER_MULTIPLY: - shader_stack[current_shader++] = blend_multiply_frag; - break; - case TRANSFER_DIVIDE: - shader_stack[current_shader++] = blend_divide_frag; - break; - case TRANSFER_MAX: - shader_stack[current_shader++] = blend_max_frag; - break; - case TRANSFER_MIN: - shader_stack[current_shader++] = blend_min_frag; - break; - } - + shader_stack[current_shader++] = overlay_shaders[config.mode]; shader_stack[current_shader++] = put_pixels_frag; unsigned int shader_id = 0; @@ -657,26 +667,26 @@ int Overlay::handle_opengl() glUseProgram(shader_id); glUniform1i(glGetUniformLocation(shader_id, "src_tex"), 0); glUniform1i(glGetUniformLocation(shader_id, "dst_tex"), 1); - if(BC_CModels::is_yuv(dst->get_color_model())) - glUniform3f(glGetUniformLocation(shader_id, "chroma_offset"), 0.0, 0.5, 0.5); - else - glUniform3f(glGetUniformLocation(shader_id, "chroma_offset"), 0.0, 0.0, 0.0); glUniform2f(glGetUniformLocation(shader_id, "dst_tex_dimensions"), - (float)dst->get_texture_w(), - (float)dst->get_texture_h()); + (float)dst->get_texture_w(), (float)dst->get_texture_h()); + float chroma_offset = BC_CModels::is_yuv(dst->get_color_model()) ? 0.5 : 0.0; + glUniform3f(glGetUniformLocation(shader_id, "chroma_offset"), + 0.0, chroma_offset, chroma_offset); - glDisable(GL_BLEND); src->draw_texture(); glUseProgram(0); + + glActiveTexture(GL_TEXTURE1); + glDisable(GL_TEXTURE_2D); + break; } - glDisable(GL_BLEND); - glActiveTexture(GL_TEXTURE1); - glDisable(GL_TEXTURE_2D); glActiveTexture(GL_TEXTURE0); glDisable(GL_TEXTURE_2D); + glDisable(GL_BLEND); - dst->set_opengl_state(VFrame::SCREEN); +// get the data before something else uses the screen + dst->screen_to_ram(); #endif return 0; }