[SceneQPainter] Per-Screen rendering

The backend can indicate that the rendering needs to be split per screen.
In that case it has to provide a different rendering buffer per screen.
The painting in the scene is adjusted to either take a splitted path
or the existing path for all screens in one go.
This commit is contained in:
Martin Gräßlin 2015-04-17 11:17:06 +02:00
parent 600b3cd2c1
commit 9133c0f9d5
2 changed files with 64 additions and 11 deletions

View file

@ -25,6 +25,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "deleted.h"
#include "effects.h"
#include "main.h"
#include "screens.h"
#include "toplevel.h"
#if HAVE_WAYLAND
#if HAVE_DRM
@ -88,6 +89,17 @@ void QPainterBackend::renderCursor(QPainter *painter)
Q_UNUSED(painter)
}
bool QPainterBackend::perScreenRendering() const
{
return false;
}
QImage *QPainterBackend::bufferForScreen(int screenId)
{
Q_UNUSED(screenId)
return buffer();
}
#if HAVE_WAYLAND
//****************************************
// WaylandQPainterBackend
@ -452,19 +464,48 @@ qint64 SceneQPainter::paint(QRegion damage, ToplevelList toplevels)
int mask = 0;
m_backend->prepareRenderingFrame();
m_painter->begin(m_backend->buffer());
if (m_backend->needsFullRepaint()) {
mask |= Scene::PAINT_SCREEN_BACKGROUND_FIRST;
damage = QRegion(0, 0, displayWidth(), displayHeight());
if (m_backend->perScreenRendering()) {
const bool needsFullRepaint = m_backend->needsFullRepaint();
if (needsFullRepaint) {
mask |= Scene::PAINT_SCREEN_BACKGROUND_FIRST;
damage = screens()->geometry();
}
QRegion overallUpdate;
for (int i = 0; i < screens()->count(); ++i) {
const QRect geometry = screens()->geometry(i);
QImage *buffer = m_backend->bufferForScreen(i);
if (!buffer || buffer->isNull()) {
continue;
}
m_painter->begin(buffer);
m_painter->save();
m_painter->setWindow(geometry);
QRegion updateRegion, validRegion;
paintScreen(&mask, damage.intersected(geometry), QRegion(), &updateRegion, &validRegion);
overallUpdate = overallUpdate.united(updateRegion);
m_painter->restore();
m_painter->end();
}
m_backend->showOverlay();
m_backend->present(mask, overallUpdate);
} else {
m_painter->begin(m_backend->buffer());
if (m_backend->needsFullRepaint()) {
mask |= Scene::PAINT_SCREEN_BACKGROUND_FIRST;
damage = QRegion(0, 0, displayWidth(), displayHeight());
}
QRegion updateRegion, validRegion;
paintScreen(&mask, damage, QRegion(), &updateRegion, &validRegion);
m_backend->renderCursor(m_painter.data());
m_backend->showOverlay();
m_painter->end();
m_backend->present(mask, updateRegion);
}
QRegion updateRegion, validRegion;
paintScreen(&mask, damage, QRegion(), &updateRegion, &validRegion);
m_backend->renderCursor(m_painter.data());
m_backend->showOverlay();
m_painter->end();
m_backend->present(mask, updateRegion);
// do cleanup
clearStackingOrder();

View file

@ -94,8 +94,20 @@ public:
}
virtual QImage *buffer() = 0;
/**
* Overload for the case that there is a different buffer per screen.
* Default implementation just calls buffer.
* @param screenId The id of the screen as used in Screens
* @todo Get a better identifier for screen then a counter variable
**/
virtual QImage *bufferForScreen(int screenId);
virtual bool needsFullRepaint() const = 0;
virtual void renderCursor(QPainter *painter);
/**
* Whether the rendering needs to be split per screen.
* Default implementation returns @c false.
**/
virtual bool perScreenRendering() const;
protected:
QPainterBackend();