Improve bbt ruler drawing performance for large time ranges.
authornick_m <mainsbridge@gmail.com>
Tue, 18 Oct 2016 16:56:43 +0000 (03:56 +1100)
committernick_m <mainsbridge@gmail.com>
Tue, 18 Oct 2016 16:56:43 +0000 (03:56 +1100)
- when the timeline displays many bars, zoom/autoscroll
  speed is improved by calculating the bbt ruler scale first
  then requesting a suitably scaled grid.

gtk2_ardour/editor.cc
gtk2_ardour/editor.h
gtk2_ardour/editor_rulers.cc
gtk2_ardour/editor_tempodisplay.cc
gtk2_ardour/tempo_lines.cc
libs/ardour/ardour/tempo.h
libs/ardour/tempo.cc

index f448f9ac2fa7693175d3c760e27a7dade525ac18..446965588d25a9e566b028f1ca279c0fe555117d 100644 (file)
@@ -2239,10 +2239,8 @@ Editor::set_snap_to (SnapType st)
        case SnapToBeatDiv4:
        case SnapToBeatDiv3:
        case SnapToBeatDiv2: {
-               std::vector<TempoMap::BBTPoint> grid;
-               compute_current_bbt_points (grid, leftmost_frame, leftmost_frame + current_page_samples());
-               compute_bbt_ruler_scale (grid, leftmost_frame, leftmost_frame + current_page_samples());
-               update_tempo_based_rulers (grid);
+               compute_bbt_ruler_scale (leftmost_frame, leftmost_frame + current_page_samples());
+               update_tempo_based_rulers ();
                break;
        }
 
@@ -4614,10 +4612,8 @@ Editor::visual_changer (const VisualChange& vc)
 
                compute_fixed_ruler_scale ();
 
-               std::vector<TempoMap::BBTPoint> grid;
-               compute_current_bbt_points (grid, vc.time_origin, pending_visual_change.time_origin + current_page_samples());
-               compute_bbt_ruler_scale (grid, vc.time_origin, pending_visual_change.time_origin + current_page_samples());
-               update_tempo_based_rulers (grid);
+               compute_bbt_ruler_scale (vc.time_origin, pending_visual_change.time_origin + current_page_samples());
+               update_tempo_based_rulers ();
 
                update_video_timeline();
        }
index 15e4c7c0bec678ce100eef8e1b6689d2b6722f5c..2c744fcf9ffd81115cf77d804207905657e4873f 100644 (file)
@@ -890,7 +890,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
        void update_just_timecode ();
        void compute_fixed_ruler_scale (); //calculates the RulerScale of the fixed rulers
        void update_fixed_rulers ();
-       void update_tempo_based_rulers (std::vector<ARDOUR::TempoMap::BBTPoint>& grid);
+       void update_tempo_based_rulers ();
        void popup_ruler_menu (framepos_t where = 0, ItemType type = RegionItem);
        void update_ruler_visibility ();
        void set_ruler_visible (RulerType, bool);
@@ -953,7 +953,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
        gint bbt_nmarks;
        uint32_t bbt_bar_helper_on;
        uint32_t bbt_accent_modulo;
-       void compute_bbt_ruler_scale (std::vector<ARDOUR::TempoMap::BBTPoint>& grid, framepos_t lower, framepos_t upper);
+       void compute_bbt_ruler_scale (framepos_t lower, framepos_t upper);
 
        ArdourCanvas::Ruler* timecode_ruler;
        ArdourCanvas::Ruler* bbt_ruler;
index 6c9e45abc88da108c021b4b800bf0f120226e770..2f12604872bfc54b142b14a68c50667e2aebb558 100644 (file)
@@ -710,14 +710,12 @@ Editor::update_fixed_rulers ()
 }
 
 void
-Editor::update_tempo_based_rulers (std::vector<TempoMap::BBTPoint>& grid)
+Editor::update_tempo_based_rulers ()
 {
        if (_session == 0) {
                return;
        }
 
-       compute_bbt_ruler_scale (grid, leftmost_frame, leftmost_frame+current_page_samples());
-
        _bbt_metric->units_per_pixel = samples_per_pixel;
 
        if (ruler_bbt_action->get_active()) {
@@ -1009,7 +1007,7 @@ Editor::metric_get_timecode (std::vector<ArdourCanvas::Ruler::Mark>& marks, gdou
 }
 
 void
-Editor::compute_bbt_ruler_scale (std::vector<ARDOUR::TempoMap::BBTPoint>& grid, framepos_t lower, framepos_t upper)
+Editor::compute_bbt_ruler_scale (framepos_t lower, framepos_t upper)
 {
        if (_session == 0) {
                return;
@@ -1107,22 +1105,17 @@ Editor::compute_bbt_ruler_scale (std::vector<ARDOUR::TempoMap::BBTPoint>& grid,
                 bbt_beat_subdivision = 4;
                break;
        }
-       if (distance (grid.begin(), grid.end()) == 0) {
+
+       const double ceil_upper_beat = floor (max (0.0, _session->tempo_map().beat_at_frame (upper))) + 1.0;
+       if (ceil_upper_beat == floor_lower_beat) {
                return;
        }
 
-       i = grid.end();
-       i--;
+       bbt_bars = _session->tempo_map().bbt_at_beat (ceil_upper_beat).bars - _session->tempo_map().bbt_at_beat (floor_lower_beat).bars;
 
-       /* XX ?? */
-       if ((*i).beat >= (*grid.begin()).beat) {
-               bbt_bars = (*i).bar - (*grid.begin()).bar;
-       } else {
-               bbt_bars = (*i).bar - (*grid.begin()).bar;
-       }
+       beats = (ceil_upper_beat - floor_lower_beat) - bbt_bars;
+       double beat_density = ((beats + 1) * ((double) (upper - lower) / (double) (1 + beat_after_upper_pos - beat_before_lower_pos))) / 5.0;
 
-       beats = distance (grid.begin(), grid.end()) - bbt_bars;
-       double beat_density = ((distance (grid.begin(), grid.end()) + 1) * ((double) (upper - lower) / (double) (1 + grid.back().frame - grid.front().frame))) / 5.0;
        /* Only show the bar helper if there aren't many bars on the screen */
        if ((bbt_bars < 2) || (beats < 5)) {
                bbt_bar_helper_on = true;
index 727473e22e40ee6b09f5d53b2952ee55f4281991..41d19ca7948ead1231a619c47730d7cb2954b1eb 100644 (file)
@@ -166,11 +166,14 @@ Editor::tempo_map_changed (const PropertyChange& /*ignored*/)
                tempo_lines->tempo_map_changed();
        }
 
+       compute_bbt_ruler_scale (leftmost_frame, leftmost_frame + current_page_samples());
        std::vector<TempoMap::BBTPoint> grid;
-       compute_current_bbt_points (grid, leftmost_frame, leftmost_frame + current_page_samples());
+       if (bbt_ruler_scale != bbt_show_many) {
+               compute_current_bbt_points (grid, leftmost_frame, leftmost_frame + current_page_samples());
+       }
        _session->tempo_map().apply_with_metrics (*this, &Editor::draw_metric_marks); // redraw metric markers
        draw_measures (grid);
-       update_tempo_based_rulers (grid);
+       update_tempo_based_rulers ();
 }
 
 struct CurveComparator {
@@ -249,10 +252,15 @@ Editor::marker_position_changed ()
                }
        }
 
+       compute_bbt_ruler_scale (leftmost_frame, leftmost_frame + current_page_samples());
        std::vector<TempoMap::BBTPoint> grid;
-       compute_current_bbt_points (grid, leftmost_frame, leftmost_frame + current_page_samples());
+
+       if (bbt_ruler_scale != bbt_show_many) {
+               compute_current_bbt_points (grid, leftmost_frame, leftmost_frame + current_page_samples());
+       }
+
        draw_measures (grid);
-       update_tempo_based_rulers (grid);
+       update_tempo_based_rulers ();
 }
 
 void
@@ -263,11 +271,15 @@ Editor::redisplay_tempo (bool immediate_redraw)
        }
 
        if (immediate_redraw) {
+               compute_bbt_ruler_scale (leftmost_frame, leftmost_frame + current_page_samples());
                std::vector<TempoMap::BBTPoint> grid;
 
-               compute_current_bbt_points (grid, leftmost_frame, leftmost_frame + current_page_samples());
+               if (bbt_ruler_scale != bbt_show_many) {
+                       compute_current_bbt_points (grid, leftmost_frame, leftmost_frame + current_page_samples());
+               }
+
                draw_measures (grid);
-               update_tempo_based_rulers (grid); // redraw rulers and measure lines
+               update_tempo_based_rulers (); // redraw rulers and measure lines
 
        } else {
                Glib::signal_idle().connect (sigc::bind_return (sigc::bind (sigc::mem_fun (*this, &Editor::redisplay_tempo), true), false));
@@ -285,7 +297,36 @@ Editor::compute_current_bbt_points (std::vector<TempoMap::BBTPoint>& grid, frame
        /* prevent negative values of leftmost from creeping into tempomap
         */
        const double lower_beat = floor (max (0.0, _session->tempo_map().beat_at_frame (leftmost))) - 1.0;
-       _session->tempo_map().get_grid (grid, max (_session->tempo_map().frame_at_beat (lower_beat), (framepos_t) 0), rightmost);
+       switch (bbt_ruler_scale) {
+
+       case bbt_show_beats:
+       case bbt_show_ticks:
+       case bbt_show_ticks_detail:
+       case bbt_show_ticks_super_detail:
+               _session->tempo_map().get_grid (grid, max (_session->tempo_map().frame_at_beat (lower_beat), (framepos_t) 0), rightmost);
+               break;
+
+       case bbt_show_1:
+               _session->tempo_map().get_grid (grid, max (_session->tempo_map().frame_at_beat (lower_beat), (framepos_t) 0), rightmost, 1);
+               break;
+
+       case bbt_show_4:
+               _session->tempo_map().get_grid (grid, max (_session->tempo_map().frame_at_beat (lower_beat), (framepos_t) 0), rightmost, 4);
+               break;
+
+       case bbt_show_16:
+               _session->tempo_map().get_grid (grid, max (_session->tempo_map().frame_at_beat (lower_beat), (framepos_t) 0), rightmost, 16);
+               break;
+
+       case bbt_show_64:
+               _session->tempo_map().get_grid (grid, max (_session->tempo_map().frame_at_beat (lower_beat), (framepos_t) 0), rightmost, 64);
+               break;
+
+       default:
+               /* bbt_show_many */
+               _session->tempo_map().get_grid (grid, max (_session->tempo_map().frame_at_beat (lower_beat), (framepos_t) 0), rightmost, 128);
+               break;
+       }
 }
 
 void
index 630e476adf82c263d68baae20a19c80edb16890d..508ae84ed9e55231ba6f307ba5737d99d0591ca7 100644 (file)
@@ -110,9 +110,22 @@ TempoLines::draw (std::vector<ARDOUR::TempoMap::BBTPoint>& grid,
        i = grid.end();
        i--;
        bars = (*i).bar - (*grid.begin()).bar;
-       beats = distance (grid.begin(), grid.end()) - bars;
 
-       beat_density = (beats * 10.0f) / lines.canvas()->width();
+       if (bars < distance (grid.begin(), grid.end()) - 1) {
+               /* grid contains beats and bars */
+               beats = distance (grid.begin(), grid.end()) - bars;
+       } else {
+               /* grid contains only bars */
+               beats = distance (grid.begin(), grid.end());
+       }
+
+       double canvas_width_used = 1.0;
+       if (leftmost_frame < grid.front().frame) {
+               const framecnt_t frame_distance = max ((framecnt_t) 1, grid.back().frame - grid.front().frame);
+               canvas_width_used = 1.0 - ((grid.front().frame - leftmost_frame) / (double) (frame_distance + grid.front().frame));
+       }
+
+       beat_density = (beats * 10.0f) / (lines.canvas()->width() * canvas_width_used);
 
        if (beat_density > 2.0f) {
                /* if the lines are too close together, they become useless */
index 99a36cafbae473b68b3fdf221a0655602d8fa5ae..3c56d74db58eb2ea424ae55dc3e9d112f5b82af5 100644 (file)
@@ -324,7 +324,7 @@ class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible
        }
 
        void get_grid (std::vector<BBTPoint>&,
-                      framepos_t start, framepos_t end);
+                      framepos_t start, framepos_t end, uint32_t bar_mod = 0);
 
        static const Tempo& default_tempo() { return _default_tempo; }
        static const Meter& default_meter() { return _default_meter; }
index 1d6f4eccf2404d67ead68ea1481bb4a943f26dc1..be8761fc39470809ae5c62ef3741775ab62cae08 100644 (file)
@@ -3500,7 +3500,7 @@ TempoMap::round_to_type (framepos_t frame, RoundMode dir, BBTPointType type)
 
 void
 TempoMap::get_grid (vector<TempoMap::BBTPoint>& points,
-                   framepos_t lower, framepos_t upper)
+                   framepos_t lower, framepos_t upper, uint32_t bar_mod)
 {
        Glib::Threads::RWLock::ReaderLock lm (lock);
        int32_t cnt = ceil (beat_at_frame_locked (_metrics, lower));
@@ -3513,14 +3513,32 @@ TempoMap::get_grid (vector<TempoMap::BBTPoint>& points,
        if (frame_at_beat_locked (_metrics, cnt) >= upper) {
                return;
        }
+       if (bar_mod == 0) {
+               while (pos >= 0 && pos < upper) {
+                       pos = frame_at_beat_locked (_metrics, cnt);
+                       const TempoSection tempo = tempo_section_at_frame_locked (_metrics, pos);
+                       const MeterSection meter = meter_section_at_frame_locked (_metrics, pos);
+                       const BBT_Time bbt = bbt_at_beat_locked (_metrics, cnt);
+                       points.push_back (BBTPoint (meter, tempo_at_frame_locked (_metrics, pos), pos, bbt.bars, bbt.beats, tempo.c_func()));
+                       ++cnt;
+               }
+       } else {
+               BBT_Time bbt = bbt_at_frame_locked (_metrics, lower);
+               bbt.beats = 1;
+               bbt.ticks = 0;
 
-       while (pos >= 0 && pos < upper) {
-               pos = frame_at_beat_locked (_metrics, cnt);
-               const TempoSection tempo = tempo_section_at_frame_locked (_metrics, pos);
-               const MeterSection meter = meter_section_at_frame_locked (_metrics, pos);
-               const BBT_Time bbt = bbt_at_beat_locked (_metrics, cnt);
-               points.push_back (BBTPoint (meter, tempo_at_frame_locked (_metrics, pos), pos, bbt.bars, bbt.beats, tempo.c_func()));
-               ++cnt;
+               if (bar_mod != 1) {
+                       bbt.bars -= bbt.bars % bar_mod;
+                       ++bbt.bars;
+               }
+
+               while (pos >= 0 && pos < upper) {
+                       pos = frame_at_bbt_locked (_metrics, bbt);
+                       const TempoSection tempo = tempo_section_at_frame_locked (_metrics, pos);
+                       const MeterSection meter = meter_section_at_frame_locked (_metrics, pos);
+                       points.push_back (BBTPoint (meter, tempo_at_frame_locked (_metrics, pos), pos, bbt.bars, bbt.beats, tempo.c_func()));
+                       bbt.bars += bar_mod;
+               }
        }
 }