Update Aurorae Shadow when we copy the buffer, not one frame after painting

Summary:
In the current code we update the shadows during the decoration paint.

Because this is called in the middle of the Scene::paintWindow and we
have already painted the shadows/built quads, the setShadow() was
deferred to avoid the obvious bugs updating the shadow would cause.
This sucks because it means we're always out by one frame, and it means
we always do two updates.

As the shadow is taken from the buffer, we can solve that problem by
updating the shadow before any painting at the same time that we update the
buffer. This means we don't need the deferring hack.

This patch also fixes a related issue that m_padding could have
changed after the buffer is rendered, but before painting. This would lead to rendering a mess.
This patch caches the relevant padding at the time the buffer is
created.

@Notmart, this is subtly different from the patch I showed you last night,
for me it fixes things without your other patch, but I don't know. If it doesn't it's
still (IMHO) a lot cleaner.

Test Plan:
Ran an Aurorae theme
Maximised, restored, resized. Everything.

Reviewers: #plasma, graesslin

Reviewed By: #plasma, graesslin

Subscribers: graesslin, plasma-devel

Tags: #plasma

Differential Revision: https://phabricator.kde.org/D4990
This commit is contained in:
David Edmundson 2017-03-20 08:51:56 +00:00
parent 4d0303fafe
commit ec4359926b
2 changed files with 17 additions and 14 deletions

View file

@ -364,6 +364,15 @@ void Decoration::init()
m_view->resetOpenGLState();
m_buffer = m_fbo->toImage();
m_contentRect = QRect(QPoint(0, 0), m_buffer.size());
if (m_padding &&
(m_padding->left() > 0 || m_padding->top() > 0 || m_padding->right() > 0 || m_padding->bottom() > 0) &&
!client().data()->isMaximized()) {
m_contentRect = m_contentRect.adjusted(m_padding->left(), m_padding->top(), -m_padding->right(), -m_padding->bottom());
}
updateShadow();
QOpenGLFramebufferObject::bindDefault();
update();
}
@ -450,13 +459,16 @@ void Decoration::paint(QPainter *painter, const QRect &repaintRegion)
{
Q_UNUSED(repaintRegion)
painter->fillRect(rect(), Qt::transparent);
QRectF r(QPointF(0, 0), m_buffer.size());
painter->drawImage(rect(), m_buffer, m_contentRect);
}
void Decoration::updateShadow()
{
bool updateShadow = false;
const auto oldShadow = shadow();
if (m_padding &&
(m_padding->left() > 0 || m_padding->top() > 0 || m_padding->right() > 0 || m_padding->bottom() > 0) &&
!client().data()->isMaximized()) {
r = r.adjusted(m_padding->left(), m_padding->top(), -m_padding->right(), -m_padding->bottom());
if (oldShadow.isNull()) {
updateShadow = true;
} else {
@ -491,24 +503,15 @@ void Decoration::paint(QPainter *painter, const QRect &repaintRegion)
m_padding->top(),
m_buffer.width() - m_padding->left() - m_padding->right(),
m_buffer.height() - m_padding->top() - m_padding->bottom()));
m_scheduledShadow = s;
setShadow(s);
}
} else {
if (!oldShadow.isNull()) {
m_scheduledShadow = QSharedPointer<KDecoration2::DecorationShadow>();
updateShadow = true;
setShadow(QSharedPointer<KDecoration2::DecorationShadow>());
}
}
if (updateShadow) {
QMetaObject::invokeMethod(this, "updateShadow", Qt::QueuedConnection);
}
painter->drawImage(rect(), m_buffer, r);
}
void Decoration::updateShadow()
{
setShadow(m_scheduledShadow);
}
QMouseEvent Decoration::translatedMouseEvent(QMouseEvent *orig)
{

View file

@ -79,6 +79,7 @@ private:
QMouseEvent translatedMouseEvent(QMouseEvent *orig);
QScopedPointer<QOpenGLFramebufferObject> m_fbo;
QImage m_buffer;
QRect m_contentRect; //the geometry of the part of the buffer that is not a shadow when buffer was created.
QPointer<QQuickWindow> m_view;
QQuickItem *m_item;
KWin::Borders *m_borders;
@ -90,7 +91,6 @@ private:
QScopedPointer<QTimer> m_updateTimer;
QScopedPointer<QOpenGLContext> m_context;
QScopedPointer<QOffscreenSurface> m_offscreenSurface;
QSharedPointer<KDecoration2::DecorationShadow> m_scheduledShadow;
QElapsedTimer m_doubleClickTimer;
};