Support software QtQuickRendering in Aurorae

Summary:
For software QtQuick rendering we want to create a pixmap buffer and
render our contents in there.

m_rendercontrol->grab does this, but also covers the GL side in pretty
much the same way that we were currently doing.

In doing so I found a bug in Qt, that's submitted upstream, and also worked round.

Test Plan:
Tested with forced software mode, could see an Aurorae decorations
Tested without (so normal code), could see an Aurorae decorations
Tested wayland on nvidia with software rendering, didn't freeze

Whether we then end up using GL, painter or xrender rendering is irrelevant
(but I tested two of them anyway)

Reviewers: #plasma, graesslin

Reviewed By: #plasma, graesslin

Subscribers: graesslin, apol, plasma-devel, kwin, #kwin

Tags: #kwin

Differential Revision: https://phabricator.kde.org/D8039
This commit is contained in:
David Edmundson 2017-11-01 15:44:57 +00:00
parent 018afd092a
commit 54b36325f7

View file

@ -324,47 +324,55 @@ void Decoration::init()
m_item->setParentItem(visualParent.value<QQuickItem*>());
visualParent.value<QQuickItem*>()->setProperty("drawBackground", false);
} else {
// first create the context
QSurfaceFormat format;
format.setDepthBufferSize(16);
format.setStencilBufferSize(8);
m_context.reset(new QOpenGLContext);
m_context->setFormat(format);
m_context->create();
// and the offscreen surface
m_offscreenSurface.reset(new QOffscreenSurface);
m_offscreenSurface->setFormat(m_context->format());
m_offscreenSurface->create();
m_renderControl = new QQuickRenderControl(this);
m_view = new QQuickWindow(m_renderControl);
bool usingGL = m_view->rendererInterface()->graphicsApi() == QSGRendererInterface::OpenGL;
m_view->setColor(Qt::transparent);
m_view->setFlags(Qt::FramelessWindowHint);
if (usingGL) {
// first create the context
QSurfaceFormat format;
format.setDepthBufferSize(16);
format.setStencilBufferSize(8);
m_context.reset(new QOpenGLContext);
m_context->setFormat(format);
m_context->create();
// and the offscreen surface
m_offscreenSurface.reset(new QOffscreenSurface);
m_offscreenSurface->setFormat(m_context->format());
m_offscreenSurface->create();
}
//workaround for https://codereview.qt-project.org/#/c/207198/
#if (QT_VERSION < QT_VERSION_CHECK(5, 10, 0))
if (!usingGL) {
m_renderControl->sync();
}
#endif
// delay rendering a little bit for better performance
m_updateTimer.reset(new QTimer);
m_updateTimer->setSingleShot(true);
m_updateTimer->setInterval(5);
connect(m_updateTimer.data(), &QTimer::timeout, this,
[this] {
if (!m_context->makeCurrent(m_offscreenSurface.data())) {
return;
}
if (m_fbo.isNull() || m_fbo->size() != m_view->size()) {
m_fbo.reset(new QOpenGLFramebufferObject(m_view->size(), QOpenGLFramebufferObject::CombinedDepthStencil));
if (!m_fbo->isValid()) {
qCWarning(AURORAE) << "Creating FBO as render target failed";
m_fbo.reset();
[this, usingGL] {
if (usingGL) {
if (!m_context->makeCurrent(m_offscreenSurface.data())) {
return;
}
if (m_fbo.isNull() || m_fbo->size() != m_view->size()) {
m_fbo.reset(new QOpenGLFramebufferObject(m_view->size(), QOpenGLFramebufferObject::CombinedDepthStencil));
if (!m_fbo->isValid()) {
qCWarning(AURORAE) << "Creating FBO as render target failed";
m_fbo.reset();
return;
}
}
m_view->setRenderTarget(m_fbo.data());
m_view->resetOpenGLState();
}
m_view->setRenderTarget(m_fbo.data());
m_renderControl->polishItems();
m_renderControl->sync();
m_renderControl->render();
m_view->resetOpenGLState();
m_buffer = m_fbo->toImage();
m_buffer = m_renderControl->grab();
m_contentRect = QRect(QPoint(0, 0), m_buffer.size());
if (m_padding &&
@ -389,9 +397,11 @@ void Decoration::init()
m_item->setParentItem(m_view->contentItem());
m_context->makeCurrent(m_offscreenSurface.data());
m_renderControl->initialize(m_context.data());
m_context->doneCurrent();
if (usingGL) {
m_context->makeCurrent(m_offscreenSurface.data());
m_renderControl->initialize(m_context.data());
m_context->doneCurrent();
}
}
setupBorders(m_item);
if (m_extendedBorders) {