summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim E. Real <termtech@rogers.com>2010-12-23 03:52:08 +0000
committerTim E. Real <termtech@rogers.com>2010-12-23 03:52:08 +0000
commit3dae7373e3325e5abe8263488913faef1c63c86b (patch)
tree8bc853dd8df0ba546bd4e78e56246e1be03ef59e
parente2930cc7ceb780eac3a43365535e04fd7189e4aa (diff)
Fixed *some* gui drawing speed issues.
-rw-r--r--muse2/ChangeLog5
-rw-r--r--muse2/muse/arranger/arranger.cpp2
-rw-r--r--muse2/muse/arranger/pcanvas.cpp42
-rw-r--r--muse2/muse/arranger/tlist.cpp7
-rw-r--r--muse2/muse/mixer/meter.cpp7
-rw-r--r--muse2/muse/widgets/scrollscale.cpp2
-rw-r--r--muse2/muse/widgets/view.cpp216
-rw-r--r--muse2/muse/widgets/view.h3
8 files changed, 248 insertions, 36 deletions
diff --git a/muse2/ChangeLog b/muse2/ChangeLog
index 0ff13419..427d840e 100644
--- a/muse2/ChangeLog
+++ b/muse2/ChangeLog
@@ -3,6 +3,11 @@
- Added some comments in app.cpp that I've been willing to include for a while. (Orcan)
- Added a line to CMakeLists to install the splash image. Commented out for now. (Orcan)
- added new-user help dialog for Input button on midi track-info (rj)
+ - Fixed *some* gui drawing speed issues. (Tim)
+ Use Qt::WA_OpaquePaintEvent for windows we fully draw on, like part canvas, track list, meter.
+ In PartCanvas::drawItem(), ignore null intersect of item bbox + rect.
+ TODO: Other windows like Slider and Knob could probably use this. And with many parts,
+ drawing is still slow (esp waves), possibly because of alpha blending.
21.12.2010:
- Moved all the config files "~/.musePrj, ~/.MusE, ~/.deicsonze.dco" into ~/.config/MusE/
and renamed them as "projects, MusE.cfg, deicsonze.dco", respectively. (Orcan)
diff --git a/muse2/muse/arranger/arranger.cpp b/muse2/muse/arranger/arranger.cpp
index 5272ee75..2173e6c7 100644
--- a/muse2/muse/arranger/arranger.cpp
+++ b/muse2/muse/arranger/arranger.cpp
@@ -379,7 +379,7 @@ Arranger::Arranger(QMainWindow* parent, const char* name)
connect(hscroll, SIGNAL(scrollChanged(int)), canvas, SLOT(setXPos(int)));
connect(hscroll, SIGNAL(scaleChanged(int)), canvas, SLOT(setXMag(int)));
connect(vscroll, SIGNAL(valueChanged(int)), list, SLOT(setYPos(int)));
- connect(hscroll, SIGNAL(scrollChanged(int)), time, SLOT(setXPos(int)));
+ connect(hscroll, SIGNAL(scrollChanged(int)), time, SLOT(setXPos(int))); //
connect(hscroll, SIGNAL(scaleChanged(int)), time, SLOT(setXMag(int)));
connect(canvas, SIGNAL(timeChanged(unsigned)), SLOT(setTime(unsigned)));
connect(canvas, SIGNAL(verticalScroll(unsigned)),SLOT(verticalScrollSetYpos(unsigned)));
diff --git a/muse2/muse/arranger/pcanvas.cpp b/muse2/muse/arranger/pcanvas.cpp
index d9c3880e..e6c30f0e 100644
--- a/muse2/muse/arranger/pcanvas.cpp
+++ b/muse2/muse/arranger/pcanvas.cpp
@@ -106,7 +106,7 @@ NPart::NPart(Part* e) : CItem(Event(), e)
{
int th = track()->height();
int y = track()->y();
- //printf("NPart::NPart track name:%s, y:%d h:%d\n", track()->name().toLatin1().constData(), y, th); // REMOVE Tim.
+ //printf("NPart::NPart track name:%s, y:%d h:%d\n", track()->name().toLatin1().constData(), y, th);
///setPos(QPoint(e->tick(), y + 1));
setPos(QPoint(e->tick(), y));
@@ -1417,26 +1417,23 @@ void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect)
if((unsigned int)to > part->lenTick())
to = part->lenTick();
+ // Item bounding box x is in tick coordinates, same as rectangle.
+ if(item->bbox().intersect(rect).isNull())
+ {
+ //printf("PartCanvas::drawItem rectangle is null\n");
+ return;
+ }
+
QRect r = item->bbox();
- //QRect r = item->bbox().intersect(rect);
- int i = part->colorIndex();
-
- //printf("part start tick %d part start pixel %d\n", part->tick(), r.x());
-
- //printf("PartCanvas::drawItem %s evRefs:%d pTick:%d pLen:%d bb.x:%d bb.w:%d rect.x:%d rect.w:%d r.x:%d r.w:%d\n", part->name().toLatin1().constData(), part->events()->arefCount(), pTick, part->lenTick(), item->bbox().x(), item->bbox().width(), rect.x(), rect.width(), r.x(), r.width());
+
+ //printf("PartCanvas::drawItem %s evRefs:%d pTick:%d pLen:%d\nbb.x:%d bb.y:%d bb.w:%d bb.h:%d\n"
+ // "rect.x:%d rect.y:%d rect.w:%d rect.h:%d\nr.x:%d r.y:%d r.w:%d r.h:%d\n",
+ // part->name().toLatin1().constData(), part->events()->arefCount(), pTick, part->lenTick(),
+ // bb.x(), bb.y(), bb.width(), bb.height(),
+ // rect.x(), rect.y(), rect.width(), rect.height(),
+ // r.x(), r.y(), r.width(), r.height());
- // THIS WAS IN MUSE-1:
- // Must be reasonable about very low negative x values! With long songs > 15min
- // and with high horizontal magnification, 'ghost' drawings appeared,
- // apparently the result of truncation later (xp = -65006 caused ghosting
- // at bar 245 with magnification at max.), even with correct clipping region
- // applied to painter in View::paint(). Tim. Apr 5 2009
- // Quote: "Warning: Note that QPainter does not attempt to work around
- // coordinate limitations in the underlying window system. Some platforms may
- // behave incorrectly with coordinates as small as +/-4000."
- //if(r.isEmpty())
- // return;
-
+ int i = part->colorIndex();
p.setPen(Qt::black);
if (part->mute()) {
QColor c(Qt::white);
@@ -1626,6 +1623,9 @@ void PartCanvas::drawMoving(QPainter& p, const CItem* item, const QRect&)
void PartCanvas::drawWavePart(QPainter& p,
const QRect& bb, WavePart* wp, const QRect& _pr)
{
+ //printf("PartCanvas::drawWavePart bb.x:%d bb.y:%d bb.w:%d bb.h:%d pr.x:%d pr.y:%d pr.w:%d pr.h:%d\n",
+ // bb.x(), bb.y(), bb.width(), bb.height(), _pr.x(), _pr.y(), _pr.width(), _pr.height());
+
QRect rr = p.worldMatrix().mapRect(bb);
QRect pr = p.worldMatrix().mapRect(_pr);
@@ -2620,7 +2620,7 @@ void PartCanvas::viewDropEvent(QDropEvent* event)
{
//printf("void PartCanvas::viewDropEvent(QDropEvent* event)\n");
if (event->source() == this) {
- printf("local DROP\n"); // REMOVE Tim
+ printf("local DROP\n");
//event->ignore(); // TODO CHECK Tim.
return;
}
@@ -2798,7 +2798,7 @@ void PartCanvas::drawCanvas(QPainter& p, const QRect& rect)
///if (/*config.canvasShowGrid ||*/ !track->isMidiTrack()) {
if (config.canvasShowGrid && (track->isMidiTrack() || track->type() == Track::WAVE)) // Tim.
{
- //printf("PartCanvas::drawCanvas track name:%s, y:%d h:%d\n", track->name().toLatin1().constData(), yy, th); // REMOVE Tim.
+ //printf("PartCanvas::drawCanvas track name:%s, y:%d h:%d\n", track->name().toLatin1().constData(), yy, th);
p.setPen(baseColor.dark(130));
///p.drawLine(x, yy, x + w, yy);
p.drawLine(x, yy + th, x + w, yy + th); // Tim.
diff --git a/muse2/muse/arranger/tlist.cpp b/muse2/muse/arranger/tlist.cpp
index f0ef8f94..1eda506e 100644
--- a/muse2/muse/arranger/tlist.cpp
+++ b/muse2/muse/arranger/tlist.cpp
@@ -59,6 +59,13 @@ static const int WHEEL_DELTA = 120;
TList::TList(Header* hdr, QWidget* parent, const char* name)
: QWidget(parent) // Qt::WNoAutoErase | Qt::WResizeNoErase are no longer needed according to Qt4 doc
{
+ setBackgroundRole(QPalette::NoRole);
+ setAttribute(Qt::WA_NoSystemBackground);
+ setAttribute(Qt::WA_StaticContents);
+ // This is absolutely required for speed! Otherwise painfully slow because we get
+ // full rect paint events even on small scrolls! See help on QPainter::scroll().
+ setAttribute(Qt::WA_OpaquePaintEvent);
+
setObjectName(name);
ypos = 0;
editMode = false;
diff --git a/muse2/muse/mixer/meter.cpp b/muse2/muse/mixer/meter.cpp
index f50aa261..eb214e77 100644
--- a/muse2/muse/mixer/meter.cpp
+++ b/muse2/muse/mixer/meter.cpp
@@ -24,6 +24,13 @@
Meter::Meter(QWidget* parent, MeterType type)
: QFrame(parent) //Qt::WNoAutoErase
{
+ setBackgroundRole(QPalette::NoRole);
+ setAttribute(Qt::WA_NoSystemBackground);
+ setAttribute(Qt::WA_StaticContents);
+ // This is absolutely required for speed! Otherwise painfully slow because we get
+ // full rect paint events even on small scrolls! See help on QPainter::scroll().
+ setAttribute(Qt::WA_OpaquePaintEvent);
+
mtype = type;
overflow = false;
val = 0.0;
diff --git a/muse2/muse/widgets/scrollscale.cpp b/muse2/muse/widgets/scrollscale.cpp
index dbced279..f279e6ce 100644
--- a/muse2/muse/widgets/scrollscale.cpp
+++ b/muse2/muse/widgets/scrollscale.cpp
@@ -265,7 +265,7 @@ ScrollScale::ScrollScale ( int s1, int s2, int cs, int max_, Qt::Orientation o,
box->addWidget ( scale, 5 );
setLayout(box);
connect ( scale, SIGNAL ( valueChanged ( int ) ), SLOT ( setScale ( int ) ) );
- connect ( scale, SIGNAL ( valueChanged ( int ) ), SIGNAL ( lscaleChanged ( int ) ) );
+ ///connect ( scale, SIGNAL ( valueChanged ( int ) ), SIGNAL ( lscaleChanged ( int ) ) ); // ??
connect ( scroll, SIGNAL ( valueChanged ( int ) ), SIGNAL ( scrollChanged ( int ) ) );
}
diff --git a/muse2/muse/widgets/view.cpp b/muse2/muse/widgets/view.cpp
index be2fb592..5bf63dc8 100644
--- a/muse2/muse/widgets/view.cpp
+++ b/muse2/muse/widgets/view.cpp
@@ -16,6 +16,12 @@
#include <QKeyEvent>
#include <QPaintEvent>
+// Don't use this, it was just for debugging.
+// It's much slower than muse-1 no matter how hard I tried.
+// The left/right pixmap shifters in seXPos setYPos
+// just ate up all the time no matter what I tried.
+//#defines VIEW_USE_DOUBLE_BUFFERING 1
+
//---------------------------------------------------------
// View::View
// double xMag = (xmag < 0) ? 1.0/-xmag : double(xmag)
@@ -24,6 +30,12 @@
View::View(QWidget* w, int xm, int ym, const char* name)
: QWidget(w)
{
+ setAttribute(Qt::WA_NoSystemBackground);
+ setAttribute(Qt::WA_StaticContents);
+ // This is absolutely required for speed! Otherwise painfully slow because we get
+ // full rect paint events even on small scrolls! See help on QPainter::scroll().
+ setAttribute(Qt::WA_OpaquePaintEvent);
+
setObjectName(QString(name));
xmag = xm;
ymag = ym;
@@ -35,6 +47,9 @@ View::View(QWidget* w, int xm, int ym, const char* name)
setBackgroundRole(QPalette::NoRole);
brush.setStyle(Qt::SolidPattern);
brush.setColor(Qt::lightGray);
+ #ifdef VIEW_USE_DOUBLE_BUFFERING
+ pmValid = false;
+ #endif
}
//---------------------------------------------------------
@@ -78,12 +93,55 @@ void View::setXPos(int x)
int delta = xpos - x; // - -> shift left
xpos = x;
- //int w = width();
- //int h = height();
+ #ifdef VIEW_USE_DOUBLE_BUFFERING
+ if (pm.isNull())
+ return;
+ if (!pmValid) {
+ //printf("View::setXPos !pmValid x:%d width:%d delta:%d\n", x, width(), delta);
+ redraw();
+ return;
+ }
+
+ int w = width();
+ int h = height();
+
+ QRect r;
+ if (delta >= w || delta <= -w)
+ r = QRect(0, 0, w, h);
+ else if (delta < 0) { // shift left
+ //bitBlt(&pm, 0, 0, &pm, -delta, 0, w + delta, h, CopyROP, true);
+ QPainter p(&pm);
+ p.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform | QPainter::HighQualityAntialiasing, false);
+ //printf("View::setXPos x:%d w:%d delta:%d r.x:%d r.w:%d\n",
+ // x, w, delta, r.x(), r.width());
+ p.drawPixmap(0, 0, pm, -delta, 0, w + delta, h);
+ r = QRect(w + delta, 0, -delta, h);
+ }
+ else { // shift right
+ //bitBlt(&pm, delta, 0, &pm, 0, 0, w-delta, h, CopyROP, true);
+ QPainter p(&pm);
+ p.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform | QPainter::HighQualityAntialiasing, false);
+ //printf("View::setXPos x:%d w:%d delta:%d r.x:%d r.w:%d\n",
+ // x, w, delta, r.x(), r.width());
+ p.drawPixmap(delta, 0, pm, 0, 0, w-delta, h);
+ r = QRect(0, 0, delta, h);
+ }
+ QRect olr = overlayRect();
+ QRect olr1(olr);
+ olr1.translate(delta, 0);
- scroll(delta, 0);
+ r |= olr;
+ r |= olr1;
- //update();
+ //printf("View::setXPos x:%d w:%d delta:%d r.x:%d r.w:%d\n", x, w, delta, r.x(), r.width());
+ //printf("View::setXPos paint delta:%d r.x:%d r.y:%d r.w:%d r.h:%d\n", delta, r.x(), r.y(), r.width(), r.height());
+
+ paint(r);
+ update();
+
+ #else
+ scroll(delta, 0);
+ #endif
}
//---------------------------------------------------------
@@ -95,21 +153,71 @@ void View::setYPos(int y)
int delta = ypos - y; // - -> shift up
ypos = y;
- //int w = width();
- //int h = height();
+ #ifdef VIEW_USE_DOUBLE_BUFFERING
+ if (pm.isNull())
+ return;
+ if (!pmValid) {
+ //printf("View::setYPos !pmValid y:%d height:%d delta:%d\n", y, height(), delta);
+
+ redraw();
+ return;
+ }
- scroll(0, delta);
+ int w = width();
+ int h = height();
+
+ QRect r;
+ if (delta >= h || delta <= -h)
+ r = QRect(0, 0, w, h);
+ else if (delta < 0) { // shift up
+ //bitBlt(&pm, 0, 0, &pm, 0, -delta, w, h + delta, CopyROP, true);
+ QPainter p(&pm);
+ p.drawPixmap(0, 0, pm, 0, -delta, w, h + delta);
+ r = QRect(0, h + delta, w, -delta);
+ }
+ else { // shift down
+ //bitBlt(&pm, 0, delta, &pm, 0, 0, w, h-delta, CopyROP, true);
+ QPainter p(&pm);
+ p.drawPixmap(0, delta, pm, 0, 0, w, h-delta);
+ r = QRect(0, 0, w, delta);
+ }
+ QRect olr = overlayRect();
+ QRect olr1(olr);
+ olr1.translate(0, delta);
+
+ r |= olr;
+ r |= olr1;
- //update();
+ //printf("View::setYPos paint delta:%d r.x:%d r.y:%d r.w:%d r.h:%d\n", delta, r.x(), r.y(), r.width(), r.height());
+
+ paint(r);
+ update();
+
+ #else
+ scroll(0, delta);
+ #endif
}
//---------------------------------------------------------
// resizeEvent
//---------------------------------------------------------
-void View::resizeEvent(QResizeEvent* /*ev*/)
+void View::resizeEvent(QResizeEvent* ev)
{
+ #ifdef VIEW_USE_DOUBLE_BUFFERING
+ //pm.resize(ev->size());
+ //printf("View::resizeEvent width:%d height:%d\n",
+ // ev->size().width(), ev->size().height());
+ if(pm.isNull())
+ {
+ //printf("View::resizeEvent pixmap is null\n");
+ pm = QPixmap(ev->size().width(), ev->size().height());
+ }
+ else
+ pm = pm.copy(QRect(QPoint(0, 0), ev->size()));
+ pmValid = false;
+ #endif
}
//---------------------------------------------------------
@@ -121,7 +229,18 @@ void View::paintEvent(QPaintEvent* ev)
//printf("View::paintEvent x:%d width:%d y:%d height:%d\n",
// ev->rect().x(), ev->rect().width(), ev->rect().y(), ev->rect().height());
+ #ifdef VIEW_USE_DOUBLE_BUFFERING
+ if (!pmValid)
+ paint(ev->rect());
+
+ //bitBlt(this, ev->rect().topLeft(), &pm, ev->rect(), CopyROP, true);
+ QPainter p(this);
+ p.setCompositionMode(QPainter::CompositionMode_Source);
+ p.drawPixmap(ev->rect().topLeft(), pm, ev->rect());
+
+ #else
paint(ev->rect());
+ #endif
}
//---------------------------------------------------------
@@ -130,7 +249,13 @@ void View::paintEvent(QPaintEvent* ev)
void View::redraw()
{
- //printf("View::redraw()\n"); // REMOVE Tim.
+ //printf("View::redraw()\n");
+
+ #ifdef VIEW_USE_DOUBLE_BUFFERING
+ QRect r(0, 0, pm.width(), pm.height());
+ //printf("View::redraw() r.x:%d r.w:%d\n", r.x(), r.width());
+ paint(r);
+ #endif
update();
}
@@ -141,7 +266,12 @@ void View::redraw()
void View::redraw(const QRect& r)
{
- //printf("View::redraw(QRect& r) r.x:%d r.w:%d\n", r.x(), r.width());
+ //printf("View::redraw(QRect& r) r.x:%d r.w:%d\n", r.x(), r.width());
+
+ #ifdef VIEW_USE_DOUBLE_BUFFERING
+ paint(r);
+ #endif
+
update(r);
}
@@ -152,17 +282,36 @@ void View::redraw(const QRect& r)
void View::paint(const QRect& r)
{
+ #ifdef VIEW_USE_DOUBLE_BUFFERING
+ if (pm.isNull())
+ return;
+ #endif
+
QRect rr(r);
- //printf("View::paint x:%d width:%d y:%d height:%d\n", r.x(), r.width(), r.y(), r.height());
+ //printf("View::paint x:%d width:%d y:%d height:%d\n", r.x(), r.width(), r.y(), r.height());
+
+ #ifdef VIEW_USE_DOUBLE_BUFFERING
+ if (!pmValid) {
+ pmValid = true;
+ rr = QRect(0, 0, pm.width(), pm.height());
+ }
+ QPainter p(&pm);
+ #else
QPainter p(this);
+ #endif
+
+ p.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform | QPainter::HighQualityAntialiasing, false);
+
if (bgPixmap.isNull())
p.fillRect(rr, brush);
else
p.drawTiledPixmap(rr, bgPixmap, QPoint(xpos + rmapx(xorg)
+ rr.x(), ypos + rmapy(yorg) + rr.y()));
+
p.setClipRegion(rr);
+
//printf("View::paint r.x:%d w:%d\n", rr.x(), rr.width());
pdraw(p, rr); // draw into pixmap
@@ -267,7 +416,7 @@ void View::setBg(const QPixmap& bgpm)
void View::pdraw(QPainter& p, const QRect& r)
{
- //printf("View::pdraw x:%d width:%d y:%d height:%d\n", r.x(), r.width(), r.y(), r.height());
+ //printf("View::pdraw virt:%d x:%d width:%d y:%d height:%d\n", virt(), r.x(), r.width(), r.y(), r.height());
if (virt()) {
setPainter(p);
@@ -304,6 +453,7 @@ void View::pdraw(QPainter& p, const QRect& r)
x = 0;
if (y < 0)
y = 0;
+
draw(p, QRect(x, y, w, h));
}
else
@@ -447,3 +597,43 @@ int View::rmapyDev(int y) const
return (y + ymag/2) / ymag;
}
+/*
+QRect View::devToVirt(const QRect& r)
+{
+ int x = r.x();
+ int y = r.y();
+ int w = r.width();
+ int h = r.height();
+ if (xmag <= 0) {
+ x -= 1;
+ w += 2;
+ x = (x + xpos + rmapx(xorg)) * (-xmag);
+ w = w * (-xmag);
+ }
+ else {
+ x = (x + xpos + rmapx(xorg)) / xmag;
+ w = (w + xmag - 1) / xmag;
+ x -= 1;
+ w += 2;
+ }
+ if (ymag <= 0) {
+ y -= 1;
+ h += 2;
+ y = (y + ypos + rmapy(yorg)) * (-ymag);
+ h = h * (-ymag);
+ }
+ else {
+ y = (y + ypos + rmapy(yorg)) / ymag;
+ h = (h + ymag - 1) / ymag;
+ y -= 1;
+ h += 2;
+ }
+
+ if (x < 0)
+ x = 0;
+ if (y < 0)
+ y = 0;
+
+ return QRect(x, y, w, h);
+}
+*/ \ No newline at end of file
diff --git a/muse2/muse/widgets/view.h b/muse2/muse/widgets/view.h
index 782a3c81..f8b0c90f 100644
--- a/muse2/muse/widgets/view.h
+++ b/muse2/muse/widgets/view.h
@@ -24,6 +24,8 @@ class QResizeEvent;
//---------------------------------------------------------
class View : public QWidget {
+ QPixmap pm; // for double buffering
+ bool pmValid;
QPixmap bgPixmap; // background Pixmap
QBrush brush;
bool _virt;
@@ -72,6 +74,7 @@ class View : public QWidget {
int mapxDev(int x) const;
int rmapy(int y) const;
int rmapyDev(int y) const;
+ //QRect devToVirt(const QRect&);
void setPainter(QPainter& p);