From a4d573f931c5752ef9f67070596c9a07e921d00a Mon Sep 17 00:00:00 2001
From: Joshua Henderson <joshua.henderson@microchip.com>
Date: Wed, 13 Sep 2017 11:04:10 -0700
Subject: [PATCH] Add support for specifying DRM dumb buffer pixel format

DRM dumb buffer suport is harded coded to ARGB32. This can be rather expensive
on unaccelerated hardware.  This adds a new environment variable
QT_QPA_FB_DRM_FORMAT that can be set to an integer QImage format to change it.
---
 .../platforms/linuxfb/qlinuxfbdrmscreen.cpp        | 26 +++++++++++++---------
 1 file changed, 16 insertions(+), 10 deletions(-)

diff --git a/src/plugins/platforms/linuxfb/qlinuxfbdrmscreen.cpp b/src/plugins/platforms/linuxfb/qlinuxfbdrmscreen.cpp
index c9fbb82..1cb82fc 100644
--- a/src/plugins/platforms/linuxfb/qlinuxfbdrmscreen.cpp
+++ b/src/plugins/platforms/linuxfb/qlinuxfbdrmscreen.cpp
@@ -43,7 +43,6 @@
 // Multiscreen: QWindow-QScreen(-output) association. Needs some reorg (device cannot be owned by screen)
 // Find card via devicediscovery like in eglfs_kms.
 // Mode restore like QEglFSKmsInterruptHandler.
-// Formats other then 32 bpp?
 // grabWindow
 
 #include "qlinuxfbdrmscreen.h"
@@ -88,7 +87,7 @@ public:
         }
     };
 
-    QLinuxFbDevice(QKmsScreenConfig *screenConfig);
+    QLinuxFbDevice(QKmsScreenConfig *screenConfig, QImage::Format format);
 
     bool open() override;
     void close() override;
@@ -117,10 +116,12 @@ private:
                                 unsigned int tv_sec, unsigned int tv_usec, void *user_data);
 
     QVector<Output> m_outputs;
+    QImage::Format m_format;
 };
 
-QLinuxFbDevice::QLinuxFbDevice(QKmsScreenConfig *screenConfig)
-    : QKmsDevice(screenConfig, QStringLiteral("/dev/dri/card0"))
+QLinuxFbDevice::QLinuxFbDevice(QKmsScreenConfig *screenConfig, QImage::Format format)
+    : QKmsDevice(screenConfig, QStringLiteral("/dev/dri/card0")),
+      m_format(format)
 {
 }
 
@@ -189,13 +190,14 @@ void QLinuxFbDevice::registerScreen(QPlatformScreen *screen,
 
 bool QLinuxFbDevice::createFramebuffer(QLinuxFbDevice::Output *output, int bufferIdx)
 {
+    const uint32_t bpp = QImage::toPixelFormat(m_format).bitsPerPixel();
     const QSize size = output->currentRes();
     const uint32_t w = size.width();
     const uint32_t h = size.height();
     drm_mode_create_dumb creq = {
         h,
         w,
-        32,
+        bpp,
         0, 0, 0, 0
     };
     if (drmIoctl(fd(), DRM_IOCTL_MODE_CREATE_DUMB, &creq) == -1) {
@@ -210,7 +212,7 @@ bool QLinuxFbDevice::createFramebuffer(QLinuxFbDevice::Output *output, int buffe
     qCDebug(qLcFbDrm, "Got a dumb buffer for size %dx%d, handle %u, pitch %u, size %u",
             w, h, fb.handle, fb.pitch, (uint) fb.size);
 
-    if (drmModeAddFB(fd(), w, h, 24, 32, fb.pitch, fb.handle, &fb.fb) == -1) {
+    if (drmModeAddFB(fd(), w, h, QImage(QSize(0,0),m_format).depth(), bpp, fb.pitch, fb.handle, &fb.fb) == -1) {
         qErrnoWarning(errno, "Failed to add FB");
         return false;
     }
@@ -232,7 +234,7 @@ bool QLinuxFbDevice::createFramebuffer(QLinuxFbDevice::Output *output, int buffe
     qCDebug(qLcFbDrm, "FB is %u, mapped at %p", fb.fb, fb.p);
     memset(fb.p, 0, fb.size);
 
-    fb.wrapper = QImage(static_cast<uchar *>(fb.p), w, h, fb.pitch, QImage::Format_ARGB32);
+    fb.wrapper = QImage(static_cast<uchar *>(fb.p), w, h, fb.pitch, m_format);
 
     return true;
 }
@@ -342,8 +344,13 @@ QLinuxFbDrmScreen::~QLinuxFbDrmScreen()
 
 bool QLinuxFbDrmScreen::initialize()
 {
+    mFormat = QImage::Format_ARGB32;
+    int format = qEnvironmentVariableIntValue("QT_QPA_FB_DRM_FORMAT");
+    if (format)
+        mFormat = QImage::Format(format);
+
     m_screenConfig = new QKmsScreenConfig;
-    m_device = new QLinuxFbDevice(m_screenConfig);
+    m_device = new QLinuxFbDevice(m_screenConfig, mFormat);
     if (!m_device->open())
         return false;
 
@@ -357,8 +364,7 @@ bool QLinuxFbDrmScreen::initialize()
     QLinuxFbDevice::Output *output(m_device->output(0));
 
     mGeometry = QRect(QPoint(0, 0), output->currentRes());
-    mDepth = 32;
-    mFormat = QImage::Format_ARGB32;
+    mDepth = QImage(QSize(0,0),mFormat).depth();
     mPhysicalSize = output->kmsOutput.physical_size;
     qCDebug(qLcFbDrm) << mGeometry << mPhysicalSize;
 
-- 
2.7.4

