https://bugs.kde.org/show_bug.cgi?id=526325

            Bug ID: 526325
           Summary: PipeWire framebuffer does not enable damage reporting,
                    causing repeated full-screen VNC updates
    Classification: Applications
           Product: krfb
      Version First unspecified
       Reported In:
          Platform: Other
                OS: Other
            Status: REPORTED
          Severity: normal
          Priority: NOR
         Component: general
          Assignee: [email protected]
          Reporter: [email protected]
  Target Milestone: ---

Created attachment 196617
  --> https://bugs.kde.org/attachment.cgi?id=196617&action=edit
Enable PipeWire damage reporting in KRFB

Title: PipeWire framebuffer does not enable damage reporting, causing repeated
full-screen VNC updates

Product: krfb
Version: 25.04.3
Platform: Linux / KDE Plasma / Wayland / PipeWire

Description

KRFB's PipeWire framebuffer already contains support for processing
PipeWireFrame::damage in PWFrameBuffer::Private::handleFrame().

However, damage reporting is not enabled on the PipeWireSourceStream.

The stream is currently initialized without calling:

stream->setDamageEnabled(true);

As a consequence, frame.damage is not available during normal operation and
handleFrame() falls back to marking the complete framebuffer as modified:

if (auto damage = frame.damage) {
    for (const auto &rect : *damage) {
        q->tiles.append(rect);
    }
} else {
    q->tiles.append(QRect(0, 0, videoSize.width(), videoSize.height()));
}

This causes KRFB to generate repeated full-screen framebuffer updates even when
only small parts of the screen have changed.

Observed behavior

Using a VNC client with framebuffer update instrumentation, KRFB 25.04.3
repeatedly produced updates covering essentially the complete 1920x1080
framebuffer.

Typical sequence:

1920x1080
1919x1079
1919x1079
1919x1079
...

This results in unnecessarily large VNC updates and significant encoding,
network and client decoding overhead.

Fix

Enabling damage reporting when the PipeWireSourceStream is created fixes the
problem:

PWFrameBuffer::Private::Private(PWFrameBuffer *q)
    : q(q)
    , stream(new PipeWireSourceStream(q))
{
    stream->setDamageEnabled(true);

    QObject::connect(stream.get(), &PipeWireSourceStream::frameReceived, q,
[this] (const PipeWireFrame &frame) {
        handleFrame(frame);
    });
}

Result after the change

After adding stream->setDamageEnabled(true), the VNC stream behaves as
expected.

There is one initial full-frame update when the client connects:

0,0 1920x1080

Subsequent updates contain the actual PipeWire damage rectangles, for example:

466,14 31x31
1246,342 32x16
1220,359 58x11
...

Instrumentation on both sides confirmed that the damage rectangles generated by
KRFB correspond to the rectangles received by the VNC client.

During a complete test run, no repeated full-screen framebuffer updates were
observed after the initial framebuffer transfer.

Patch

--- a/framebuffers/pipewire/pw_framebuffer.cpp
+++ b/framebuffers/pipewire/pw_framebuffer.cpp
@@ -111,6 +111,7 @@ PWFrameBuffer::Private::Private(PWFrameBuffer *q)
     : q(q)
     , stream(new PipeWireSourceStream(q))
 {
+    stream->setDamageEnabled(true);
     QObject::connect(stream.get(), &PipeWireSourceStream::frameReceived, q,
[this] (const PipeWireFrame &frame) {
         handleFrame(frame);
     });

I have also attached this change as krfb-pipewire-enable-damage.patch.

-- 
You are receiving this mail because:
You are watching all bug changes.

Reply via email to