forked from qt-creator/qt-creator
QmlProfiler: Make sure UI is properly rendered
Do the QML based painting when requested inside the UI thread, and only copy the final canvas pixmap in the renderer thread (in paint()). To avoid excessive re-drawing delay the painting via a timer to the next event loop run. The previous logic was still from Qt Quick 1 times, where the paint() method was called in the GUI thread. This has changed in Qt Quick 2: Here the paint() method will be called (on Unix) in a separate renderer thread, making the drawRegion / onDrawRegion connections implicitly deferred. Change-Id: I298547013658e4cd1e94115305577bdb96cd0b2a Reviewed-by: Ulf Hermann <ulf.hermann@digia.com> Reviewed-by: Kai Koehne <kai.koehne@digia.com>
This commit is contained in:
@@ -937,9 +937,6 @@ void Context2D::setupPainter()
|
||||
|
||||
void Context2D::beginPainting()
|
||||
{
|
||||
if (m_width <= 0 || m_height <=0)
|
||||
return;
|
||||
|
||||
if (m_pixmap.width() != m_width || m_pixmap.height() != m_height) {
|
||||
if (m_painter.isActive())
|
||||
m_painter.end();
|
||||
|
||||
@@ -39,36 +39,45 @@ namespace Internal {
|
||||
|
||||
QmlProfilerCanvas::QmlProfilerCanvas()
|
||||
: m_context2d(new Context2D(this))
|
||||
, m_dirty(true)
|
||||
{
|
||||
setAcceptedMouseButtons(Qt::LeftButton);
|
||||
m_drawTimer.setSingleShot(true);
|
||||
connect(&m_drawTimer, SIGNAL(timeout()), this, SLOT(draw()));
|
||||
|
||||
m_drawTimer.start();
|
||||
}
|
||||
|
||||
void QmlProfilerCanvas::requestPaint()
|
||||
{
|
||||
if (m_context2d->size().width() != width()
|
||||
|| m_context2d->size().height() != height()) {
|
||||
m_drawTimer.start();
|
||||
} else {
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void QmlProfilerCanvas::requestRedraw()
|
||||
{
|
||||
setDirty(true);
|
||||
m_drawTimer.start();
|
||||
}
|
||||
|
||||
// called from GUI thread. Draws into m_context2d.
|
||||
void QmlProfilerCanvas::draw()
|
||||
{
|
||||
QMutexLocker lock(&m_pixmapMutex);
|
||||
m_context2d->reset();
|
||||
m_context2d->setSize(width(), height());
|
||||
|
||||
if (width() != 0 && height() != 0)
|
||||
emit drawRegion(m_context2d, QRect(0, 0, width(), height()));
|
||||
update();
|
||||
}
|
||||
|
||||
// called from OpenGL thread. Renders m_context2d into OpenGL buffer.
|
||||
void QmlProfilerCanvas::paint(QPainter *p)
|
||||
{
|
||||
if (m_context2d->size().width() != width() || m_context2d->size().height() != height()) {
|
||||
m_dirty = true;
|
||||
m_context2d->setSize(width(), height());
|
||||
}
|
||||
|
||||
if (m_dirty) {
|
||||
m_context2d->reset();
|
||||
|
||||
emit drawRegion(m_context2d, QRect(0, 0, width(), height()));
|
||||
setDirty(false);
|
||||
}
|
||||
|
||||
QMutexLocker lock(&m_pixmapMutex);
|
||||
p->drawPixmap(0, 0, m_context2d->pixmap());
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,8 @@
|
||||
#define QMLPROFILERCANVAS_H
|
||||
|
||||
#include <QQuickPaintedItem>
|
||||
#include <QTimer>
|
||||
#include <QMutex>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class Context2D;
|
||||
@@ -43,29 +45,19 @@ class QmlProfilerCanvas : public QQuickPaintedItem
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(bool dirty READ dirty WRITE setDirty NOTIFY dirtyChanged)
|
||||
|
||||
public:
|
||||
QmlProfilerCanvas();
|
||||
|
||||
bool dirty() const { return m_dirty; }
|
||||
void setDirty(bool dirty)
|
||||
{
|
||||
if (m_dirty != dirty) {
|
||||
m_dirty = dirty;
|
||||
emit dirtyChanged(dirty);
|
||||
}
|
||||
}
|
||||
|
||||
signals:
|
||||
void dirtyChanged(bool dirty);
|
||||
|
||||
void drawRegion(Context2D *ctxt, const QRect ®ion);
|
||||
|
||||
public slots:
|
||||
void requestPaint();
|
||||
void requestRedraw();
|
||||
|
||||
private slots:
|
||||
void draw();
|
||||
|
||||
protected:
|
||||
virtual void paint(QPainter *);
|
||||
virtual void componentComplete();
|
||||
@@ -73,7 +65,8 @@ protected:
|
||||
private:
|
||||
Context2D *m_context2d;
|
||||
|
||||
bool m_dirty;
|
||||
QTimer m_drawTimer;
|
||||
QMutex m_pixmapMutex;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user