[Interest] Qt 5.5 LinuxFb Plugin with Base Layer Transparency

Peter Seiderer ps.report at gmx.net
Thu Apr 7 23:34:56 CEST 2016


Hello Jack,

> Our application requires that we blend 3 layers with 3 framebuffers on a TI
> device. The base layer is opaque video, the middle layer is video blended
> on top of the base layer with a global alpha channel that we need to be
> able to modify on the fly, and a top GUI layer with transparency. This
> approach worked great with Qt 4.8 and we are trying to get it to work with
> Qt 5.5.
>
> The problem is that when we run the top level GUI application, we cannot
> set the background of the to be fully transparent. It simply appears black.
> This covers the 2 lower z-order applications and they are no longer visible.
>
> We attempted to investigate this issue by looking at the Qt5.5 linuxfb
> plugin source code. Beginning at line 251 of qfbscreen.cpp in the Qt5.5
> source ( located in qt5base-5.5.1/src/platformsupport/fbconvenience ), we
> see where the linuxfb plugin sets the base layer to black. If we change
> that one line to "qt::transparent", and re-launch our app, then we see the
> lower 2 layers "through" the GUI in the regions of the GUI where it is
> fully transparent. Initially, the fully transparent GUI displays correctly.
> It displays a menu, which initially appears correct. A problem occurs when
> we then try to hide the menu. It remains displayed on the screen.
> Apparently, the redraw of the base layer, which is transparent, does not
> replace the pixels from the menu, but is instead blended with the menu
> pixels.
>
> We have tried several composition modes in the base layer's paint event,
> including Source and Clear, but neither fixes the problem. On previous
> products ( using the DM3730 ), we used this same approach ( DSS blended
> framebuffers ) with Qt 4.8 and it worked as expected. How can we make this
> work with Qt 5.5?
>

Did have the same problem (but on a NXP/Freescale i.MX6 board), solved it
by the following patch/hack for Qt5.4.1 and a simple OSD GUI:

--- begin ---
From dab806c4dce22efc5eb6615287cf803a1d72ee6a Mon Sep 17 00:00:00 2001
From: Peter Seiderer <ps.report at gmx.net>
Date: Tue, 30 Sep 2014 16:53:00 +0200
Subject: [PATCH] platforms/linuxfb: enabel alpha channel on framebuffer output

---
 src/platformsupport/fbconvenience/qfbscreen.cpp  | 9 +++++++--
 src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp | 4 +++-
 2 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/src/platformsupport/fbconvenience/qfbscreen.cpp b/src/platformsupport/fbconvenience/qfbscreen.cpp
index aa35825..6670f8e 100644
--- a/src/platformsupport/fbconvenience/qfbscreen.cpp
+++ b/src/platformsupport/fbconvenience/qfbscreen.cpp
@@ -217,8 +217,13 @@ QRegion QFbScreen::doRedraw()
     if (!mIsUpToDate)
         generateRects();

-    if (!mCompositePainter)
+    if (!mCompositePainter) {
         mCompositePainter = new QPainter(mScreenImage);
+        // simple solution for OSD rendering (real solution should invalidate/init
+        // background always before rendering widget content with alpha blending)
+        mCompositePainter->setCompositionMode(QPainter::CompositionMode_Source);
+    }
+
     for (int rectIndex = 0; rectIndex < mRepaintRegion.rectCount(); rectIndex++) {
         QRegion rectRegion = rects[rectIndex];

@@ -236,7 +241,7 @@ QRegion QFbScreen::doRedraw()
             foreach (const QRect &rect, intersect.rects()) {
                 bool firstLayer = true;
                 if (layer == -1) {
-                    mCompositePainter->fillRect(rect, Qt::black);
+                    mCompositePainter->fillRect(rect, Qt::transparent);
                     firstLayer = false;
                     layer = mWindowStack.size() - 1;
                 }
diff --git a/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp b/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp
index a66c9fa..522088c 100644
--- a/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp
+++ b/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp
@@ -431,8 +431,10 @@ QRegion QLinuxFbScreen::doRedraw()
     if (touched.isEmpty())
         return touched;

-    if (!mBlitter)
+    if (!mBlitter) {
         mBlitter = new QPainter(&mFbScreenImage);
+        mBlitter->setCompositionMode(QPainter::CompositionMode_Source);
+    }

     QVector<QRect> rects = touched.rects();
     for (int i = 0; i < rects.size(); i++)
--
2.1.4
--- end ---

Regards,
Peter

> qfbscreen.cpp:
>
>         // we only expect one rectangle, but defensive coding...
>         foreach (const QRect &rect, intersect.rects()) {
>             bool firstLayer = true;
>             if (layer == -1) {
>                 mCompositePainter->fillRect(rect, Qt::black);
>                 firstLayer = false;
>                 layer = mWindowStack.size() - 1;
>             }
>
>             for (int layerIndex = layer; layerIndex != -1; layerIndex--) {
>                 if (!mWindowStack[layerIndex]->window()->isVisible())
>                     continue;
>                 // if (mWindowStack[layerIndex]->isMinimized())
>                 //     continue;
>
>                 QRect windowRect =
> mWindowStack[layerIndex]->geometry().translated(-screenOffset);
>                 QRect windowIntersect = rect.translated(-windowRect.left(),
>                                                         -windowRect.top());
>
>
>                 QFbBackingStore *backingStore =
> mWindowStack[layerIndex]->backingStore();
>
>                 if (backingStore) {
>                     backingStore->lock();
>                     mCompositePainter->drawImage(rect,
> backingStore->image(), windowIntersect);
>                     backingStore->unlock();
>                 }
>                 if (firstLayer) {
>                     firstLayer = false;
>                 }
>             }
>         }
> We greatly appreciate any help - thank you.



More information about the Interest mailing list