mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-06 06:44:57 +01:00
An actual tempo line cache (not quite perfect when scrolling left, but miles ahead of the previous one didn't really help at all).
Tempo line updating done immediately/directly rather than in an idle handler. Looking for feedback how this works for other people, performance wise... Feel-wise, the obvious lag between scrolling and tempo lines being drawn is now gone. git-svn-id: svn://localhost/ardour2/branches/3.0@3799 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
81c571f2f0
commit
95d82d7a16
7 changed files with 149 additions and 67 deletions
|
|
@ -85,6 +85,7 @@
|
|||
#include "simpleline.h"
|
||||
#include "rhythm_ferret.h"
|
||||
#include "actions.h"
|
||||
#include "tempo_lines.h"
|
||||
|
||||
#ifdef FFT_ANALYSIS
|
||||
#include "analysis_window.h"
|
||||
|
|
@ -376,7 +377,6 @@ Editor::Editor ()
|
|||
|
||||
range_marker_drag_rect = 0;
|
||||
marker_drag_line = 0;
|
||||
tempo_map_change_idle_handler_id = -1;
|
||||
set_midi_edit_mode (MidiEditPencil, true);
|
||||
set_mouse_mode (MouseObject, true);
|
||||
|
||||
|
|
@ -3938,6 +3938,8 @@ Editor::set_show_measures (bool yn)
|
|||
hide_measures ();
|
||||
|
||||
if ((_show_measures = yn) == true) {
|
||||
if (tempo_lines)
|
||||
tempo_lines->show();
|
||||
draw_measures ();
|
||||
}
|
||||
instant_save ();
|
||||
|
|
@ -4542,6 +4544,9 @@ Editor::set_frames_per_unit (double fpu)
|
|||
if (max_frames / fpu < 800.0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (tempo_lines)
|
||||
tempo_lines->tempo_map_changed();
|
||||
|
||||
frames_per_unit = fpu;
|
||||
post_zoom ();
|
||||
|
|
|
|||
|
|
@ -1597,7 +1597,6 @@ public:
|
|||
void draw_metric_marks (const ARDOUR::Metrics& metrics);
|
||||
|
||||
void compute_current_bbt_points (nframes_t left, nframes_t right);
|
||||
int tempo_map_change_idle_handler_id;
|
||||
void tempo_map_changed (ARDOUR::Change);
|
||||
void redisplay_tempo (bool immediate_redraw);
|
||||
|
||||
|
|
|
|||
|
|
@ -904,7 +904,8 @@ Editor::canvas_scroll_to (nframes64_t time_origin)
|
|||
|
||||
update_fixed_rulers ();
|
||||
|
||||
redisplay_tempo (!_dragging_hscrollbar);
|
||||
//redisplay_tempo (!_dragging_hscrollbar);
|
||||
redisplay_tempo (true);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -102,12 +102,13 @@ Editor::tempo_map_changed (Change ignored)
|
|||
|
||||
ENSURE_GUI_THREAD(bind (mem_fun (*this, &Editor::tempo_map_changed), ignored));
|
||||
|
||||
if (tempo_lines)
|
||||
tempo_lines->tempo_map_changed();
|
||||
|
||||
compute_current_bbt_points(leftmost_frame, leftmost_frame + (nframes_t)(edit_packer.get_width() * frames_per_unit));
|
||||
session->tempo_map().apply_with_metrics (*this, &Editor::draw_metric_marks); // redraw metric markers
|
||||
update_tempo_based_rulers ();
|
||||
if (tempo_map_change_idle_handler_id < 0) {
|
||||
tempo_map_change_idle_handler_id = Glib::signal_idle().connect (mem_fun (*this, &Editor::redraw_measures));
|
||||
}
|
||||
redraw_measures ();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -119,20 +120,7 @@ Editor::redisplay_tempo (bool immediate_redraw)
|
|||
|
||||
compute_current_bbt_points (leftmost_frame, leftmost_frame + (nframes_t)(edit_packer.get_width() * frames_per_unit)); // redraw rulers and measures
|
||||
|
||||
if (immediate_redraw) {
|
||||
|
||||
hide_measures ();
|
||||
|
||||
if (current_bbt_points) {
|
||||
draw_measures ();
|
||||
}
|
||||
|
||||
} else if (tempo_map_change_idle_handler_id < 0) {
|
||||
|
||||
tempo_map_change_idle_handler_id = Glib::signal_idle().connect (mem_fun (*this, &Editor::redraw_measures));
|
||||
|
||||
}
|
||||
|
||||
redraw_measures();
|
||||
update_tempo_based_rulers ();
|
||||
}
|
||||
|
||||
|
|
@ -182,9 +170,7 @@ Editor::hide_measures ()
|
|||
bool
|
||||
Editor::redraw_measures ()
|
||||
{
|
||||
hide_measures ();
|
||||
draw_measures ();
|
||||
tempo_map_change_idle_handler_id = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,35 +22,52 @@
|
|||
#include "tempo_lines.h"
|
||||
#include "ardour_ui.h"
|
||||
|
||||
ArdourCanvas::SimpleLine *
|
||||
TempoLines::get_line ()
|
||||
using namespace std;
|
||||
|
||||
#define MAX_CACHED_LINES 512
|
||||
|
||||
TempoLines::TempoLines(ArdourCanvas::Canvas& canvas, ArdourCanvas::Group* group)
|
||||
: _canvas(canvas)
|
||||
, _group(group)
|
||||
, _clean_left(DBL_MAX)
|
||||
, _clean_right(0.0)
|
||||
{
|
||||
ArdourCanvas::SimpleLine *line;
|
||||
|
||||
if (_free_lines.empty()) {
|
||||
line = new ArdourCanvas::SimpleLine (*_group);
|
||||
_used_lines.push_back (line);
|
||||
} else {
|
||||
line = _free_lines.front();
|
||||
_free_lines.erase (_free_lines.begin());
|
||||
_used_lines.push_back (line);
|
||||
}
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
void
|
||||
TempoLines::tempo_map_changed()
|
||||
{
|
||||
_clean_left = DBL_MAX;
|
||||
_clean_right = 0.0;
|
||||
|
||||
// TODO: Dirty/slow, but 'needed' for zoom :(
|
||||
for (Lines::iterator i = _lines.begin(); i != _lines.end(); ) {
|
||||
Lines::iterator next = i;
|
||||
++next;
|
||||
i->second->property_x1() = DBL_MAX;
|
||||
i->second->property_x2() = DBL_MAX;
|
||||
_lines.erase(i);
|
||||
_lines.insert(make_pair(DBL_MAX, i->second));
|
||||
i = next;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TempoLines::show ()
|
||||
{
|
||||
for (Lines::iterator i = _lines.begin(); i != _lines.end(); ++i) {
|
||||
i->second->show();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TempoLines::hide ()
|
||||
{
|
||||
for (Lines::iterator i = _used_lines.begin(); i != _used_lines.end(); ++i) {
|
||||
(*i)->hide();
|
||||
_free_lines.push_back (*i);
|
||||
for (Lines::iterator i = _lines.begin(); i != _lines.end(); ++i) {
|
||||
i->second->hide();
|
||||
}
|
||||
_used_lines.clear ();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TempoLines::draw (ARDOUR::TempoMap::BBTPointList& points, double frames_per_unit)
|
||||
{
|
||||
|
|
@ -63,6 +80,8 @@ TempoLines::draw (ARDOUR::TempoMap::BBTPointList& points, double frames_per_unit
|
|||
uint32_t beats = 0;
|
||||
uint32_t bars = 0;
|
||||
uint32_t color;
|
||||
|
||||
const size_t needed = points.size();
|
||||
|
||||
_canvas.get_scroll_region (x1, y1, x2, who_cares);
|
||||
_canvas.root()->get_bounds(who_cares, who_cares, who_cares, y2);
|
||||
|
|
@ -74,14 +93,38 @@ TempoLines::draw (ARDOUR::TempoMap::BBTPointList& points, double frames_per_unit
|
|||
bars = (*i).bar - (*points.begin()).bar;
|
||||
beats = points.size() - bars;
|
||||
|
||||
beat_density = (beats * 10.0f) / _canvas.get_width ();
|
||||
beat_density = (beats * 10.0f) / _canvas.get_width ();
|
||||
|
||||
if (beat_density > 4.0f) {
|
||||
/* if the lines are too close together, they become useless
|
||||
*/
|
||||
/* if the lines are too close together, they become useless */
|
||||
return;
|
||||
}
|
||||
|
||||
xpos = rint(((nframes64_t)(*i).frame) / (double)frames_per_unit);
|
||||
const double needed_right = xpos;
|
||||
|
||||
i = points.begin();
|
||||
|
||||
xpos = rint(((nframes64_t)(*i).frame) / (double)frames_per_unit);
|
||||
const double needed_left = xpos;
|
||||
|
||||
Lines::iterator left = _lines.lower_bound(xpos); // first line >= xpos
|
||||
|
||||
bool exhausted = (left == _lines.end());
|
||||
Lines::iterator li = left;
|
||||
|
||||
// Tempo map hasn't changed and we're entirely within a clean
|
||||
// range, don't need to do anything. Yay.
|
||||
if (needed_left >= _clean_left && needed_right <= _clean_right) {
|
||||
//cout << "LINE CACHE PERFECT HIT!" << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
//cout << "LINE CACHE MISS :/" << endl;
|
||||
|
||||
bool inserted_last_time = false;
|
||||
bool invalidated = false;
|
||||
|
||||
for (i = points.begin(); i != points.end(); ++i) {
|
||||
|
||||
switch ((*i).type) {
|
||||
|
|
@ -96,21 +139,63 @@ TempoLines::draw (ARDOUR::TempoMap::BBTPointList& points, double frames_per_unit
|
|||
color = ARDOUR_UI::config()->canvasvar_MeasureLineBeat.get();
|
||||
|
||||
if (beat_density > 2.0) {
|
||||
/* only draw beat lines if the gaps between beats are large.
|
||||
*/
|
||||
/* only draw beat lines if the gaps between beats are large. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
xpos = rint(((nframes64_t)(*i).frame) / (double)frames_per_unit);
|
||||
line = get_line ();
|
||||
line->property_x1() = xpos;
|
||||
line->property_x2() = xpos;
|
||||
line->property_y2() = y2;
|
||||
line->property_color_rgba() = color;
|
||||
//line->raise_to_top();
|
||||
line->show();
|
||||
|
||||
if (inserted_last_time) {
|
||||
li = _lines.lower_bound(xpos); // first line >= xpos
|
||||
}
|
||||
|
||||
if (!exhausted) {
|
||||
line = li->second;
|
||||
exhausted = ((++li) == _lines.end());
|
||||
inserted_last_time = false;
|
||||
} else if (_lines.size() < needed || _lines.size() < MAX_CACHED_LINES) {
|
||||
line = new ArdourCanvas::SimpleLine (*_group);
|
||||
line->property_x1() = xpos;
|
||||
line->property_x2() = xpos;
|
||||
line->property_y2() = y2;
|
||||
line->property_color_rgba() = color;
|
||||
_lines.insert(make_pair(xpos, line));
|
||||
inserted_last_time = true;
|
||||
} else {
|
||||
assert(li != _lines.begin());
|
||||
line = _lines.begin()->second; // steal leftmost line
|
||||
_lines.erase(_lines.begin());
|
||||
_lines.insert(make_pair(xpos, line));
|
||||
inserted_last_time = true;
|
||||
invalidated = true;
|
||||
}
|
||||
|
||||
/* At this point, line's key is correct, but actual pos may not be */
|
||||
if (line->property_x1() != xpos) {
|
||||
// Turn this on to see the case where this isn't quite ideal yet
|
||||
// (scrolling left, lots of lines are moved left when there is
|
||||
// likely to be a huge chunk with equivalent coords)
|
||||
//cout << "MOVE " << line->property_x1() << " -> " << xpos << endl;
|
||||
double x1 = line->property_x1();
|
||||
bool was_clean = x1 >= _clean_left && x1 <= _clean_right;
|
||||
invalidated = invalidated || was_clean;
|
||||
line->property_x1() = xpos;
|
||||
line->property_x2() = xpos;
|
||||
line->property_y2() = y2;
|
||||
line->property_color_rgba() = color;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (invalidated) { // We messed things up, visible range is all we know is valid
|
||||
_clean_left = needed_left;
|
||||
_clean_right = needed_right;
|
||||
} else { // Extend range to what we've 'fixed'
|
||||
_clean_left = min(_clean_left, needed_left);
|
||||
_clean_right = max(_clean_right, needed_right);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,30 +19,39 @@
|
|||
#ifndef __ardour_tempo_lines_h__
|
||||
#define __ardour_tempo_lines_h__
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <boost/pool/pool.hpp>
|
||||
#include <boost/pool/pool_alloc.hpp>
|
||||
#include <ardour/tempo.h>
|
||||
#include "canvas.h"
|
||||
#include "simpleline.h"
|
||||
|
||||
typedef boost::fast_pool_allocator<
|
||||
std::pair<double, ArdourCanvas::SimpleLine>,
|
||||
boost::default_user_allocator_new_delete,
|
||||
boost::details::pool::null_mutex,
|
||||
8192>
|
||||
MapAllocator;
|
||||
|
||||
class TempoLines {
|
||||
public:
|
||||
TempoLines(ArdourCanvas::Canvas& canvas, ArdourCanvas::Group* group)
|
||||
: _canvas(canvas)
|
||||
, _group(group)
|
||||
{}
|
||||
|
||||
ArdourCanvas::SimpleLine* get_line();
|
||||
TempoLines(ArdourCanvas::Canvas& canvas, ArdourCanvas::Group* group);
|
||||
|
||||
void tempo_map_changed();
|
||||
|
||||
void draw(ARDOUR::TempoMap::BBTPointList& points, double frames_per_unit);
|
||||
|
||||
void show();
|
||||
void hide();
|
||||
|
||||
private:
|
||||
typedef std::vector<ArdourCanvas::SimpleLine*> Lines;
|
||||
Lines _free_lines;
|
||||
Lines _used_lines;
|
||||
typedef std::map<double, ArdourCanvas::SimpleLine*, std::less<double>, MapAllocator> Lines;
|
||||
Lines _lines;
|
||||
|
||||
ArdourCanvas::Canvas& _canvas;
|
||||
ArdourCanvas::Group* _group;
|
||||
double _clean_left;
|
||||
double _clean_right;
|
||||
};
|
||||
|
||||
#endif /* __ardour_tempo_lines_h__ */
|
||||
|
|
|
|||
|
|
@ -27,9 +27,6 @@
|
|||
#include <sigc++/signal.h>
|
||||
#include <glibmm/thread.h>
|
||||
|
||||
#include <boost/pool/pool.hpp>
|
||||
#include <boost/pool/pool_alloc.hpp>
|
||||
|
||||
#include <pbd/undo.h>
|
||||
#include <pbd/xml++.h>
|
||||
#include <pbd/statefuldestructible.h>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue