From 5c79f777a4bf280eea85d4252f94d8a61aeb8ff4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= <mgraesslin@kde.org>
Date: Fri, 17 Apr 2015 11:18:58 +0200
Subject: [PATCH] [SceneQPainter] Render per DrmOutput in DrmQPainterBackend

For each DrmOutput a set of buffers is created and presented. The
renderig is still in one go and not synced to the individual screens.

Dynamic changes are not yet supported.
---
 scene_qpainter.cpp | 49 ++++++++++++++++++++++++++++++++++------------
 scene_qpainter.h   | 11 +++++++++--
 2 files changed, 46 insertions(+), 14 deletions(-)

diff --git a/scene_qpainter.cpp b/scene_qpainter.cpp
index f3f89c7eec..8400db0499 100644
--- a/scene_qpainter.cpp
+++ b/scene_qpainter.cpp
@@ -356,24 +356,38 @@ DrmQPainterBackend::DrmQPainterBackend(DrmBackend *backend)
     , QPainterBackend()
     , m_backend(backend)
 {
-
-    m_buffer[0] = m_backend->createBuffer(m_backend->size());
-    m_buffer[0]->map();
-    m_buffer[1] = m_backend->createBuffer(m_backend->size());
-    m_buffer[1]->map();
-    m_buffer[0]->image()->fill(Qt::black);
-    m_buffer[1]->image()->fill(Qt::black);
+    const auto outputs = m_backend->outputs();
+    for (auto output: outputs) {
+        Output o;
+        auto initBuffer = [&o, output, this] (int index) {
+            o.buffer[index] = m_backend->createBuffer(output->size());
+            o.buffer[index]->map();
+            o.buffer[index]->image()->fill(Qt::black);
+        };
+        initBuffer(0);
+        initBuffer(1);
+        o.output = output;
+        m_outputs << o;
+    }
 }
 
 DrmQPainterBackend::~DrmQPainterBackend()
 {
-    delete m_buffer[0];
-    delete m_buffer[1];
+    for (auto it = m_outputs.begin(); it != m_outputs.end(); ++it) {
+        delete (*it).buffer[0];
+        delete (*it).buffer[1];
+    }
 }
 
 QImage *DrmQPainterBackend::buffer()
 {
-    return m_buffer[m_bufferIndex]->image();
+    return bufferForScreen(0);
+}
+
+QImage *DrmQPainterBackend::bufferForScreen(int screenId)
+{
+    const Output &o = m_outputs.at(screenId);
+    return o.buffer[o.index]->image();
 }
 
 bool DrmQPainterBackend::needsFullRepaint() const
@@ -383,7 +397,9 @@ bool DrmQPainterBackend::needsFullRepaint() const
 
 void DrmQPainterBackend::prepareRenderingFrame()
 {
-    m_bufferIndex = (m_bufferIndex + 1) % 2;
+    for (auto it = m_outputs.begin(); it != m_outputs.end(); ++it) {
+        (*it).index = ((*it).index + 1) % 2;
+    }
 }
 
 void DrmQPainterBackend::present(int mask, const QRegion &damage)
@@ -393,13 +409,22 @@ void DrmQPainterBackend::present(int mask, const QRegion &damage)
     if (!VirtualTerminal::self()->isActive()) {
         return;
     }
-    m_backend->present(m_buffer[m_bufferIndex]);
+    for (auto it = m_outputs.begin(); it != m_outputs.end(); ++it) {
+        const Output &o = *it;
+        m_backend->present(o.buffer[o.index], o.output);
+    }
 }
 
 bool DrmQPainterBackend::usesOverlayWindow() const
 {
     return false;
 }
+
+bool DrmQPainterBackend::perScreenRendering() const
+{
+    return true;
+}
+
 #endif
 
 #endif
diff --git a/scene_qpainter.h b/scene_qpainter.h
index 760b99d312..73484323c8 100644
--- a/scene_qpainter.h
+++ b/scene_qpainter.h
@@ -46,6 +46,7 @@ class WaylandBackend;
 }
 class DrmBackend;
 class DrmBuffer;
+class DrmOutput;
 class FramebufferBackend;
 class X11WindowedBackend;
 
@@ -198,15 +199,21 @@ public:
     virtual ~DrmQPainterBackend();
 
     QImage *buffer() override;
+    QImage *bufferForScreen(int screenId);
     bool needsFullRepaint() const override;
     bool usesOverlayWindow() const override;
     void prepareRenderingFrame() override;
     void present(int mask, const QRegion &damage) override;
+    bool perScreenRendering() const override;
 
 private:
+    struct Output {
+        DrmBuffer *buffer[2];
+        DrmOutput *output;
+        int index = 0;
+    };
+    QVector<Output> m_outputs;
     DrmBackend *m_backend;
-    DrmBuffer *m_buffer[2];
-    int m_bufferIndex = 0;
 };
 #endif