[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.
This commit is contained in:
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;
};
}