[aurorae] Hack to get Aurorae work with compositing

This is a temporary solution! A proper solution needs changes in
libkdecoration and paint redirector.

The hack redirects the rendering into an FBO. After each rendering we
get a QImage from the FBO and store that in a buffer. As we unfortunately
do not know what changed, we schedule a complete update on the deco's
widget. Once we get the paint event we just render the buffer on the
widget. And thus we have copied the content to a place where it
integrates with the paint redirector.

As already written, this is a horrible hack and I'm not proud about it.
There are just too many copies involved.

So how to improve?
* deco should be able to just provide a QImage to the PaintRedirector
  without the paint to the QWidget.
* only do the FBO -> QImage step if it is needed by the compositor, that
  is compress the events
* for OpenGL compositing it would be totally awesome if we could just
  make the contexts sharing so that we can just reuse the texture from
  the FBO directly.
icc-effect-5.14.5
Martin Gräßlin 2013-10-02 14:54:43 +02:00
parent 93c2eea528
commit dd6598c1ff
2 changed files with 28 additions and 0 deletions

View File

@ -21,6 +21,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <QApplication>
#include <QDebug>
#include <QOpenGLFramebufferObject>
#include <QPainter>
#include <QQmlComponent>
#include <QQmlContext>
#include <QQmlEngine>
@ -259,6 +261,24 @@ void AuroraeClient::init()
widget()->setAttribute(Qt::WA_NoSystemBackground);
widget()->installEventFilter(this);
m_view = new QQuickWindow();
if (compositingActive()) {
connect(m_view, &QQuickWindow::beforeRendering, [this]() {
if (m_fbo.isNull() || m_fbo->size() != QSize(width(), height())) {
m_fbo.reset(new QOpenGLFramebufferObject(QSize(width(), height()), QOpenGLFramebufferObject::CombinedDepthStencil));
if (!m_fbo->isValid()) {
qWarning() << "Creating FBO as render target failed";
m_fbo.reset();
return;
}
}
m_view->setRenderTarget(m_fbo.data());
});
connect(m_view, &QQuickWindow::afterRendering, [this]{
m_buffer = m_fbo->toImage();
});
connect(m_view, &QQuickWindow::afterRendering, widget(),
static_cast<void (QWidget::*)(void)>(&QWidget::update), Qt::QueuedConnection);
}
m_view->setColor(Qt::transparent);
m_container = QWidget::createWindowContainer(m_view, widget(), Qt::X11BypassWindowManagerHint);
m_container->setAttribute(Qt::WA_TranslucentBackground);
@ -275,6 +295,11 @@ void AuroraeClient::init()
bool AuroraeClient::eventFilter(QObject *object, QEvent *event)
{
if (compositingActive() && !m_fbo.isNull() && object == widget() && QEvent::Paint) {
QPainter painter(widget());
painter.drawImage(QPoint(0, 0), m_buffer);
return false;
}
// we need to filter the wheel events on the decoration
// QML does not yet provide a way to accept wheel events, this will change with Qt 5
// TODO: remove in KDE5

View File

@ -23,6 +23,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <kdecoration.h>
#include <kdecorationfactory.h>
class QOpenGLFramebufferObject;
class QQmlComponent;
class QQmlEngine;
class QQuickItem;
@ -160,6 +161,8 @@ private:
QQuickWindow *m_view;
QQuickItem *m_item;
QWidget *m_container;
QScopedPointer<QOpenGLFramebufferObject> m_fbo;
QImage m_buffer;
};
}