Qt LinuxFB旋转界面和触摸

15 篇文章 0 订阅
9 篇文章 1 订阅

一.修改源代码

需要修改qtbase/src/plugins/platforms/linuxfb目录下得qlinuxfbscreen.h和qlinuxfbscreen.cpp文件

二.修改后的源代码

头文件qlinuxfbscreen.h

/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
 
#ifndef QLINUXFBSCREEN_H
#define QLINUXFBSCREEN_H
 
//#include <QtFbSupport/private/qfbscreen_p.h>
//#include <QtPlatformSupport/private/qfbscreen_p.h>
#include <QtFbSupport/private/qfbscreen_p.h>

QT_BEGIN_NAMESPACE
 
class QPainter;
class QFbCursor;
 
class QLinuxFbScreen : public QFbScreen
{
    Q_OBJECT
public:
    QLinuxFbScreen(const QStringList &args);
    ~QLinuxFbScreen();
 
    bool initialize();
 
    QPixmap grabWindow(WId wid, int x, int y, int width, int height) const Q_DECL_OVERRIDE;
 
    QRegion doRedraw() Q_DECL_OVERRIDE;
 
private:
    QStringList mArgs;
    int mFbFd;
    int mTtyFd;
	// add by immortal start
	int mRotation;
	// add by immortal end
    QImage mFbScreenImage;
    int mBytesPerLine;
    int mOldTtyMode;
 
    struct {
        uchar *data;
        int offset, size;
    } mMmap;
 
    QPainter *mBlitter;
};
 
QT_END_NAMESPACE
 
#endif // QLINUXFBSCREEN_H

c文件qlinuxfbscreen.cpp

/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
 
#include "qlinuxfbscreen.h"
/*
#include <QtFbSupport/private/qfbcursor_p.h>
#include <QtFbSupport/private/qfbwindow_p.h>
*/
//#include <QtPlatformSupport/private/qfbcursor_p.h>
#include <QtFbSupport/private/qfbcursor_p.h>
//#include <QtPlatformSupport/private/qfbwindow_p.h>
#include <QtFbSupport/private/qfbwindow_p.h>
#include <QtCore/QFile>
#include <QtCore/QRegularExpression>
#include <QtGui/QPainter>
 
#include <private/qcore_unix_p.h> // overrides QT_OPEN
#include <qimage.h>
#include <qdebug.h>
 
#include <unistd.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <linux/kd.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <limits.h>
#include <signal.h>
 
#include <linux/fb.h>

 
QT_BEGIN_NAMESPACE
 
static int openFramebufferDevice(const QString &dev)
{
    int fd = -1;
 
    if (access(dev.toLatin1().constData(), R_OK|W_OK) == 0)
        fd = QT_OPEN(dev.toLatin1().constData(), O_RDWR);
 
    if (fd == -1) {
        if (access(dev.toLatin1().constData(), R_OK) == 0)
            fd = QT_OPEN(dev.toLatin1().constData(), O_RDONLY);
    }
 
    return fd;
}
 
static int determineDepth(const fb_var_screeninfo &vinfo)
{
    int depth = vinfo.bits_per_pixel;
    if (depth== 24) {
        depth = vinfo.red.length + vinfo.green.length + vinfo.blue.length;
        if (depth <= 0)
            depth = 24; // reset if color component lengths are not reported
    } else if (depth == 16) {
        depth = vinfo.red.length + vinfo.green.length + vinfo.blue.length;
        if (depth <= 0)
            depth = 16;
    }
    return depth;
}
 
static QRect determineGeometry(const fb_var_screeninfo &vinfo, const QRect &userGeometry)
{
    int xoff = vinfo.xoffset;
    int yoff = vinfo.yoffset;
    int w, h;
    if (userGeometry.isValid()) {
        w = userGeometry.width();
        h = userGeometry.height();
        if ((uint)w > vinfo.xres)
            w = vinfo.xres;
        if ((uint)h > vinfo.yres)
            h = vinfo.yres;
 
        int xxoff = userGeometry.x(), yyoff = userGeometry.y();
        if (xxoff != 0 || yyoff != 0) {
            if (xxoff < 0 || xxoff + w > (int)(vinfo.xres))
                xxoff = vinfo.xres - w;
            if (yyoff < 0 || yyoff + h > (int)(vinfo.yres))
                yyoff = vinfo.yres - h;
            xoff += xxoff;
            yoff += yyoff;
        } else {
            xoff += (vinfo.xres - w)/2;
            yoff += (vinfo.yres - h)/2;
        }
    } else {
        w = vinfo.xres;
        h = vinfo.yres;
    }
 
    if (w == 0 || h == 0) {
        qWarning("Unable to find screen geometry, using 320x240");
        w = 320;
        h = 240;
    }
 
    return QRect(xoff, yoff, w, h);
}
 
static QSizeF determinePhysicalSize(const fb_var_screeninfo &vinfo, const QSize &mmSize, const QSize &res)
{
    int mmWidth = mmSize.width(), mmHeight = mmSize.height();
 
    if (mmWidth <= 0 && mmHeight <= 0) {
        if (vinfo.width != 0 && vinfo.height != 0
            && vinfo.width != UINT_MAX && vinfo.height != UINT_MAX) {
            mmWidth = vinfo.width;
            mmHeight = vinfo.height;
        } else {
            const int dpi = 100;
            mmWidth = qRound(res.width() * 25.4 / dpi);
            mmHeight = qRound(res.height() * 25.4 / dpi);
        }
    } else if (mmWidth > 0 && mmHeight <= 0) {
        mmHeight = res.height() * mmWidth/res.width();
    } else if (mmHeight > 0 && mmWidth <= 0) {
        mmWidth = res.width() * mmHeight/res.height();
    }
 
    return QSize(mmWidth, mmHeight);
}
 
static QImage::Format determineFormat(const fb_var_screeninfo &info, int depth)
{
    const fb_bitfield rgba[4] = { info.red, info.green,
                                  info.blue, info.transp };
 
    QImage::Format format = QImage::Format_Invalid;
 
    switch (depth) {
    case 32: {
        const fb_bitfield argb8888[4] = {{16, 8, 0}, {8, 8, 0},
                                         {0, 8, 0}, {24, 8, 0}};
        const fb_bitfield abgr8888[4] = {{0, 8, 0}, {8, 8, 0},
                                         {16, 8, 0}, {24, 8, 0}};
        if (memcmp(rgba, argb8888, 4 * sizeof(fb_bitfield)) == 0) {
            format = QImage::Format_ARGB32;
        } else if (memcmp(rgba, argb8888, 3 * sizeof(fb_bitfield)) == 0) {
            format = QImage::Format_RGB32;
        } else if (memcmp(rgba, abgr8888, 3 * sizeof(fb_bitfield)) == 0) {
            format = QImage::Format_RGB32;
            // pixeltype = BGRPixel;
        }
        break;
    }
    case 24: {
        const fb_bitfield rgb888[4] = {{16, 8, 0}, {8, 8, 0},
                                       {0, 8, 0}, {0, 0, 0}};
        const fb_bitfield bgr888[4] = {{0, 8, 0}, {8, 8, 0},
                                       {16, 8, 0}, {0, 0, 0}};
        if (memcmp(rgba, rgb888, 3 * sizeof(fb_bitfield)) == 0) {
            format = QImage::Format_RGB888;
        } else if (memcmp(rgba, bgr888, 3 * sizeof(fb_bitfield)) == 0) {
            format = QImage::Format_RGB888;
            // pixeltype = BGRPixel;
        }
        break;
    }
    case 18: {
        const fb_bitfield rgb666[4] = {{12, 6, 0}, {6, 6, 0},
                                       {0, 6, 0}, {0, 0, 0}};
        if (memcmp(rgba, rgb666, 3 * sizeof(fb_bitfield)) == 0)
            format = QImage::Format_RGB666;
        break;
    }
    case 16: {
        const fb_bitfield rgb565[4] = {{11, 5, 0}, {5, 6, 0},
                                       {0, 5, 0}, {0, 0, 0}};
        const fb_bitfield bgr565[4] = {{0, 5, 0}, {5, 6, 0},
                                       {11, 5, 0}, {0, 0, 0}};
        if (memcmp(rgba, rgb565, 3 * sizeof(fb_bitfield)) == 0) {
            format = QImage::Format_RGB16;
        } else if (memcmp(rgba, bgr565, 3 * sizeof(fb_bitfield)) == 0) {
            format = QImage::Format_RGB16;
            // pixeltype = BGRPixel;
        }
        break;
    }
    case 15: {
        const fb_bitfield rgb1555[4] = {{10, 5, 0}, {5, 5, 0},
                                        {0, 5, 0}, {15, 1, 0}};
        const fb_bitfield bgr1555[4] = {{0, 5, 0}, {5, 5, 0},
                                        {10, 5, 0}, {15, 1, 0}};
        if (memcmp(rgba, rgb1555, 3 * sizeof(fb_bitfield)) == 0) {
            format = QImage::Format_RGB555;
        } else if (memcmp(rgba, bgr1555, 3 * sizeof(fb_bitfield)) == 0) {
            format = QImage::Format_RGB555;
            // pixeltype = BGRPixel;
        }
        break;
    }
    case 12: {
        const fb_bitfield rgb444[4] = {{8, 4, 0}, {4, 4, 0},
                                       {0, 4, 0}, {0, 0, 0}};
        if (memcmp(rgba, rgb444, 3 * sizeof(fb_bitfield)) == 0)
            format = QImage::Format_RGB444;
        break;
    }
    case 8:
        break;
    case 1:
        format = QImage::Format_Mono; //###: LSB???
        break;
    default:
        break;
    }
	qDebug() << "*******************************************" << format << "************************************************";
    return format;
}
 
static int openTtyDevice(const QString &device)
{
    const char *const devs[] = { "/dev/tty0", "/dev/tty", "/dev/console", 0 };
 
    int fd = -1;
    if (device.isEmpty()) {
        for (const char * const *dev = devs; *dev; ++dev) {
            fd = QT_OPEN(*dev, O_RDWR);
            if (fd != -1)
                break;
        }
    } else {
        fd = QT_OPEN(QFile::encodeName(device).constData(), O_RDWR);
    }
 
    return fd;
}
 
static void switchToGraphicsMode(int ttyfd, bool doSwitch, int *oldMode)
{
    // Do not warn if the switch fails: the ioctl fails when launching from a
    // remote console and there is nothing we can do about it.  The matching
    // call in resetTty should at least fail then, too, so we do no harm.
    if (ioctl(ttyfd, KDGETMODE, oldMode) == 0) {
        if (doSwitch && *oldMode != KD_GRAPHICS)
            ioctl(ttyfd, KDSETMODE, KD_GRAPHICS);
    }
}
 
static void resetTty(int ttyfd, int oldMode)
{
    ioctl(ttyfd, KDSETMODE, oldMode);
 
    QT_CLOSE(ttyfd);
}
 
static void blankScreen(int fd, bool on)
{
    ioctl(fd, FBIOBLANK, on ? VESA_POWERDOWN : VESA_NO_BLANKING);
}
 
QLinuxFbScreen::QLinuxFbScreen(const QStringList &args)
    : mArgs(args), mFbFd(-1), mTtyFd(-1), mBlitter(0),mRotation(0)
{
    mMmap.data = 0;
}
 
QLinuxFbScreen::~QLinuxFbScreen()
{
    if (mFbFd != -1) {
        if (mMmap.data)
            munmap(mMmap.data - mMmap.offset, mMmap.size);
        close(mFbFd);
    }
 
    if (mTtyFd != -1)
        resetTty(mTtyFd, mOldTtyMode);
 
    delete mBlitter;
}
 
bool QLinuxFbScreen::initialize()
{
    QRegularExpression ttyRx(QLatin1String("tty=(.*)"));
    QRegularExpression fbRx(QLatin1String("fb=(.*)"));
    QRegularExpression mmSizeRx(QLatin1String("mmsize=(\\d+)x(\\d+)"));
    QRegularExpression sizeRx(QLatin1String("size=(\\d+)x(\\d+)"));
    QRegularExpression offsetRx(QLatin1String("offset=(\\d+)x(\\d+)"));
	// add by immorta start
	QRegularExpression rotationRx(QLatin1String("rotation=(0|90|180|270)"));
	// add by immorta end
    QString fbDevice, ttyDevice;
    QSize userMmSize;
    QRect userGeometry;
    bool doSwitchToGraphicsMode = true;
 
    // Parse arguments
    
    //for (const QString &arg : qAsConst(mArgs)) {
    //   foreach (const QString &arg, mArgs) {
     for (const QString &arg : qAsConst(mArgs)) {
        QRegularExpressionMatch match;
        if (arg == QLatin1String("nographicsmodeswitch"))
            doSwitchToGraphicsMode = false;
        else if (arg.contains(mmSizeRx, &match))
            userMmSize = QSize(match.captured(1).toInt(), match.captured(2).toInt());
        else if (arg.contains(sizeRx, &match))
            userGeometry.setSize(QSize(match.captured(1).toInt(), match.captured(2).toInt()));
        else if (arg.contains(offsetRx, &match))
            userGeometry.setTopLeft(QPoint(match.captured(1).toInt(), match.captured(2).toInt()));
        else if (arg.contains(ttyRx, &match))
            ttyDevice = match.captured(1);
        else if (arg.contains(fbRx, &match))
            fbDevice = match.captured(1);
		// add by immortal start
		else if (arg.contains(rotationRx, &match))
			mRotation = match.captured(1).toInt();
		// add by immortal end
    }
 
    if (fbDevice.isEmpty()) {
        fbDevice = QLatin1String("/dev/fb0");
        if (!QFile::exists(fbDevice))
            fbDevice = QLatin1String("/dev/graphics/fb0");
        if (!QFile::exists(fbDevice)) {
            qWarning("Unable to figure out framebuffer device. Specify it manually.");
            return false;
        }
    }
 
    // Open the device
    mFbFd = openFramebufferDevice(fbDevice);
    if (mFbFd == -1) {
        qErrnoWarning(errno, "Failed to open framebuffer %s", qPrintable(fbDevice));
        return false;
    }
 
    // Read the fixed and variable screen information
    fb_fix_screeninfo finfo;
    fb_var_screeninfo vinfo;
    memset(&vinfo, 0, sizeof(vinfo));
    memset(&finfo, 0, sizeof(finfo));
 
    if (ioctl(mFbFd, FBIOGET_FSCREENINFO, &finfo) != 0) {
        qErrnoWarning(errno, "Error reading fixed information");
        return false;
    }
 
    if (ioctl(mFbFd, FBIOGET_VSCREENINFO, &vinfo)) {
        qErrnoWarning(errno, "Error reading variable information");
        return false;
    }
 
    mDepth = determineDepth(vinfo);
    mBytesPerLine = finfo.line_length;
    QRect geometry = determineGeometry(vinfo, userGeometry);
	// add by immortal start
	QRect originalGeometry = geometry;
	if( 90 == mRotation  || 270 == mRotation )
    {
		int tmp = geometry.width();
        geometry.setWidth(geometry.height());
        geometry.setHeight(tmp);
    }
	// add by immortal end
    mGeometry = QRect(QPoint(0, 0), geometry.size());
    mFormat = determineFormat(vinfo, mDepth);
	
    //mPhysicalSize = determinePhysicalSize(vinfo, userMmSize, geometry.size());
	mPhysicalSize = determinePhysicalSize(vinfo, userMmSize, originalGeometry.size());
    // mmap the framebuffer
    mMmap.size = finfo.smem_len;
    uchar *data = (unsigned char *)mmap(0, mMmap.size, PROT_READ | PROT_WRITE, MAP_SHARED, mFbFd, 0);
    if ((long)data == -1) {
        qErrnoWarning(errno, "Failed to mmap framebuffer");
        return false;
    }
 
    //mMmap.offset = geometry.y() * mBytesPerLine + geometry.x() * mDepth / 8;
	mMmap.offset = originalGeometry.y() * mBytesPerLine + originalGeometry.x() * mDepth / 8;
    mMmap.data = data + mMmap.offset;
 
    QFbScreen::initializeCompositor();
    //mFbScreenImage = QImage(mMmap.data, geometry.width(), geometry.height(), mBytesPerLine, mFormat);
	mFbScreenImage = QImage(mMmap.data, originalGeometry.width(), originalGeometry.height(), mBytesPerLine, mFormat);
 
    mCursor = new QFbCursor(this);
 
    mTtyFd = openTtyDevice(ttyDevice);
    if (mTtyFd == -1)
        qErrnoWarning(errno, "Failed to open tty");
 
    switchToGraphicsMode(mTtyFd, doSwitchToGraphicsMode, &mOldTtyMode);
    blankScreen(mFbFd, false);
 
    return true;
}
 
QRegion QLinuxFbScreen::doRedraw()
{
    QRegion touched = QFbScreen::doRedraw();
 
    if (touched.isEmpty())
        return touched;
 
    if (!mBlitter)
        mBlitter = new QPainter(&mFbScreenImage);
 
	const QVector<QRect> rects = touched.rects();
    mBlitter->setCompositionMode(QPainter::CompositionMode_Source);
	for (int i = 0; i < rects.size(); ++i)
	{
		if( 90 == mRotation || 270 == mRotation )
        {
			mBlitter->translate(mGeometry.height()/2, mGeometry.width()/2);
        }
        else if( 180 == mRotation )
        {
            mBlitter->translate(mGeometry.width()/2, mGeometry.height()/2);
        }
        if( mRotation != 0 )
        {
            mBlitter->rotate(mRotation);
            mBlitter->translate(-mGeometry.width()/2, -mGeometry.height()/2);
        }
        mBlitter->drawImage(rects[i], mScreenImage, rects[i]);
		mBlitter->resetTransform();
    }
    return touched;
}
 
// grabWindow() grabs "from the screen" not from the backingstores.
// In linuxfb's case it will also include the mouse cursor.
QPixmap QLinuxFbScreen::grabWindow(WId wid, int x, int y, int width, int height) const
{
    if (!wid) {
        if (width < 0)
            width = mFbScreenImage.width() - x;
        if (height < 0)
            height = mFbScreenImage.height() - y;
        return QPixmap::fromImage(mFbScreenImage).copy(x, y, width, height);
    }
 
    QFbWindow *window = windowForId(wid);
    if (window) {
        const QRect geom = window->geometry();
        if (width < 0)
            width = geom.width() - x;
        if (height < 0)
            height = geom.height() - y;
        QRect rect(geom.topLeft() + QPoint(x, y), QSize(width, height));
        rect &= window->geometry();
        return QPixmap::fromImage(mFbScreenImage).copy(rect);
    }
 
    return QPixmap();
}
 
QT_END_NAMESPACE

三对应的补丁文件

头文件补丁code_h.patch

--- /home/mywork/qtSrc/qt-everywhere-src-5.12.9/qtbase/src/plugins/platforms/linuxfb/qlinuxfbscreen.h	2020-06-03 03:51:20.000000000 -0700
+++ ./qlinuxfbscreen.h	2020-09-24 04:14:14.923500800 -0700
@@ -36,48 +36,52 @@
 ** $QT_END_LICENSE$
 **
 ****************************************************************************/
-
+ 
 #ifndef QLINUXFBSCREEN_H
 #define QLINUXFBSCREEN_H
-
+ 
+//#include <QtFbSupport/private/qfbscreen_p.h>
+//#include <QtPlatformSupport/private/qfbscreen_p.h>
 #include <QtFbSupport/private/qfbscreen_p.h>
 
 QT_BEGIN_NAMESPACE
-
+ 
 class QPainter;
 class QFbCursor;
-
+ 
 class QLinuxFbScreen : public QFbScreen
 {
     Q_OBJECT
 public:
     QLinuxFbScreen(const QStringList &args);
     ~QLinuxFbScreen();
-
-    bool initialize() override;
-
-    QPixmap grabWindow(WId wid, int x, int y, int width, int height) const override;
-
-    QRegion doRedraw() override;
-
+ 
+    bool initialize();
+ 
+    QPixmap grabWindow(WId wid, int x, int y, int width, int height) const Q_DECL_OVERRIDE;
+ 
+    QRegion doRedraw() Q_DECL_OVERRIDE;
+ 
 private:
     QStringList mArgs;
     int mFbFd;
     int mTtyFd;
-
+	// add by immortal start
+	int mRotation;
+	// add by immortal end
     QImage mFbScreenImage;
     int mBytesPerLine;
     int mOldTtyMode;
-
+ 
     struct {
         uchar *data;
         int offset, size;
     } mMmap;
-
+ 
     QPainter *mBlitter;
 };
-
+ 
 QT_END_NAMESPACE
-
+ 
 #endif // QLINUXFBSCREEN_H
-
+ 

C文件补丁code_c.patch

--- /home/mywork/qtSrc/qt-everywhere-src-5.12.9/qtbase/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp	2020-06-03 03:51:20.000000000 -0700
+++ ./qlinuxfbscreen.cpp	2020-09-24 04:19:03.311256600 -0700
@@ -36,18 +36,24 @@
 ** $QT_END_LICENSE$
 **
 ****************************************************************************/
-
+ 
 #include "qlinuxfbscreen.h"
+/*
+#include <QtFbSupport/private/qfbcursor_p.h>
+#include <QtFbSupport/private/qfbwindow_p.h>
+*/
+//#include <QtPlatformSupport/private/qfbcursor_p.h>
 #include <QtFbSupport/private/qfbcursor_p.h>
+//#include <QtPlatformSupport/private/qfbwindow_p.h>
 #include <QtFbSupport/private/qfbwindow_p.h>
 #include <QtCore/QFile>
 #include <QtCore/QRegularExpression>
 #include <QtGui/QPainter>
-
+ 
 #include <private/qcore_unix_p.h> // overrides QT_OPEN
 #include <qimage.h>
 #include <qdebug.h>
-
+ 
 #include <unistd.h>
 #include <stdlib.h>
 #include <sys/ioctl.h>
@@ -60,26 +66,27 @@
 #include <stdio.h>
 #include <limits.h>
 #include <signal.h>
-
+ 
 #include <linux/fb.h>
 
+ 
 QT_BEGIN_NAMESPACE
-
+ 
 static int openFramebufferDevice(const QString &dev)
 {
     int fd = -1;
-
+ 
     if (access(dev.toLatin1().constData(), R_OK|W_OK) == 0)
         fd = QT_OPEN(dev.toLatin1().constData(), O_RDWR);
-
+ 
     if (fd == -1) {
         if (access(dev.toLatin1().constData(), R_OK) == 0)
             fd = QT_OPEN(dev.toLatin1().constData(), O_RDONLY);
     }
-
+ 
     return fd;
 }
-
+ 
 static int determineDepth(const fb_var_screeninfo &vinfo)
 {
     int depth = vinfo.bits_per_pixel;
@@ -94,7 +101,7 @@
     }
     return depth;
 }
-
+ 
 static QRect determineGeometry(const fb_var_screeninfo &vinfo, const QRect &userGeometry)
 {
     int xoff = vinfo.xoffset;
@@ -107,7 +114,7 @@
             w = vinfo.xres;
         if ((uint)h > vinfo.yres)
             h = vinfo.yres;
-
+ 
         int xxoff = userGeometry.x(), yyoff = userGeometry.y();
         if (xxoff != 0 || yyoff != 0) {
             if (xxoff < 0 || xxoff + w > (int)(vinfo.xres))
@@ -124,20 +131,20 @@
         w = vinfo.xres;
         h = vinfo.yres;
     }
-
+ 
     if (w == 0 || h == 0) {
         qWarning("Unable to find screen geometry, using 320x240");
         w = 320;
         h = 240;
     }
-
+ 
     return QRect(xoff, yoff, w, h);
 }
-
+ 
 static QSizeF determinePhysicalSize(const fb_var_screeninfo &vinfo, const QSize &mmSize, const QSize &res)
 {
     int mmWidth = mmSize.width(), mmHeight = mmSize.height();
-
+ 
     if (mmWidth <= 0 && mmHeight <= 0) {
         if (vinfo.width != 0 && vinfo.height != 0
             && vinfo.width != UINT_MAX && vinfo.height != UINT_MAX) {
@@ -153,17 +160,17 @@
     } else if (mmHeight > 0 && mmWidth <= 0) {
         mmWidth = res.width() * mmHeight/res.height();
     }
-
+ 
     return QSize(mmWidth, mmHeight);
 }
-
+ 
 static QImage::Format determineFormat(const fb_var_screeninfo &info, int depth)
 {
     const fb_bitfield rgba[4] = { info.red, info.green,
                                   info.blue, info.transp };
-
+ 
     QImage::Format format = QImage::Format_Invalid;
-
+ 
     switch (depth) {
     case 32: {
         const fb_bitfield argb8888[4] = {{16, 8, 0}, {8, 8, 0},
@@ -241,14 +248,14 @@
     default:
         break;
     }
-
+	qDebug() << "*******************************************" << format << "************************************************";
     return format;
 }
-
+ 
 static int openTtyDevice(const QString &device)
 {
     const char *const devs[] = { "/dev/tty0", "/dev/tty", "/dev/console", 0 };
-
+ 
     int fd = -1;
     if (device.isEmpty()) {
         for (const char * const *dev = devs; *dev; ++dev) {
@@ -259,10 +266,10 @@
     } else {
         fd = QT_OPEN(QFile::encodeName(device).constData(), O_RDWR);
     }
-
+ 
     return fd;
 }
-
+ 
 static void switchToGraphicsMode(int ttyfd, bool doSwitch, int *oldMode)
 {
     // Do not warn if the switch fails: the ioctl fails when launching from a
@@ -273,25 +280,25 @@
             ioctl(ttyfd, KDSETMODE, KD_GRAPHICS);
     }
 }
-
+ 
 static void resetTty(int ttyfd, int oldMode)
 {
     ioctl(ttyfd, KDSETMODE, oldMode);
-
+ 
     QT_CLOSE(ttyfd);
 }
-
+ 
 static void blankScreen(int fd, bool on)
 {
     ioctl(fd, FBIOBLANK, on ? VESA_POWERDOWN : VESA_NO_BLANKING);
 }
-
+ 
 QLinuxFbScreen::QLinuxFbScreen(const QStringList &args)
-    : mArgs(args), mFbFd(-1), mTtyFd(-1), mBlitter(0)
+    : mArgs(args), mFbFd(-1), mTtyFd(-1), mBlitter(0),mRotation(0)
 {
     mMmap.data = 0;
 }
-
+ 
 QLinuxFbScreen::~QLinuxFbScreen()
 {
     if (mFbFd != -1) {
@@ -299,13 +306,13 @@
             munmap(mMmap.data - mMmap.offset, mMmap.size);
         close(mFbFd);
     }
-
+ 
     if (mTtyFd != -1)
         resetTty(mTtyFd, mOldTtyMode);
-
+ 
     delete mBlitter;
 }
-
+ 
 bool QLinuxFbScreen::initialize()
 {
     QRegularExpression ttyRx(QLatin1String("tty=(.*)"));
@@ -313,14 +320,19 @@
     QRegularExpression mmSizeRx(QLatin1String("mmsize=(\\d+)x(\\d+)"));
     QRegularExpression sizeRx(QLatin1String("size=(\\d+)x(\\d+)"));
     QRegularExpression offsetRx(QLatin1String("offset=(\\d+)x(\\d+)"));
-
+	// add by immorta start
+	QRegularExpression rotationRx(QLatin1String("rotation=(0|90|180|270)"));
+	// add by immorta end
     QString fbDevice, ttyDevice;
     QSize userMmSize;
     QRect userGeometry;
     bool doSwitchToGraphicsMode = true;
-
+ 
     // Parse arguments
-    for (const QString &arg : qAsConst(mArgs)) {
+    
+    //for (const QString &arg : qAsConst(mArgs)) {
+    //   foreach (const QString &arg, mArgs) {
+     for (const QString &arg : qAsConst(mArgs)) {
         QRegularExpressionMatch match;
         if (arg == QLatin1String("nographicsmodeswitch"))
             doSwitchToGraphicsMode = false;
@@ -334,8 +346,12 @@
             ttyDevice = match.captured(1);
         else if (arg.contains(fbRx, &match))
             fbDevice = match.captured(1);
+		// add by immortal start
+		else if (arg.contains(rotationRx, &match))
+			mRotation = match.captured(1).toInt();
+		// add by immortal end
     }
-
+ 
     if (fbDevice.isEmpty()) {
         fbDevice = QLatin1String("/dev/fb0");
         if (!QFile::exists(fbDevice))
@@ -345,37 +361,47 @@
             return false;
         }
     }
-
+ 
     // Open the device
     mFbFd = openFramebufferDevice(fbDevice);
     if (mFbFd == -1) {
         qErrnoWarning(errno, "Failed to open framebuffer %s", qPrintable(fbDevice));
         return false;
     }
-
+ 
     // Read the fixed and variable screen information
     fb_fix_screeninfo finfo;
     fb_var_screeninfo vinfo;
     memset(&vinfo, 0, sizeof(vinfo));
     memset(&finfo, 0, sizeof(finfo));
-
+ 
     if (ioctl(mFbFd, FBIOGET_FSCREENINFO, &finfo) != 0) {
         qErrnoWarning(errno, "Error reading fixed information");
         return false;
     }
-
+ 
     if (ioctl(mFbFd, FBIOGET_VSCREENINFO, &vinfo)) {
         qErrnoWarning(errno, "Error reading variable information");
         return false;
     }
-
+ 
     mDepth = determineDepth(vinfo);
     mBytesPerLine = finfo.line_length;
     QRect geometry = determineGeometry(vinfo, userGeometry);
+	// add by immortal start
+	QRect originalGeometry = geometry;
+	if( 90 == mRotation  || 270 == mRotation )
+    {
+		int tmp = geometry.width();
+        geometry.setWidth(geometry.height());
+        geometry.setHeight(tmp);
+    }
+	// add by immortal end
     mGeometry = QRect(QPoint(0, 0), geometry.size());
     mFormat = determineFormat(vinfo, mDepth);
-    mPhysicalSize = determinePhysicalSize(vinfo, userMmSize, geometry.size());
-
+	
+    //mPhysicalSize = determinePhysicalSize(vinfo, userMmSize, geometry.size());
+	mPhysicalSize = determinePhysicalSize(vinfo, userMmSize, originalGeometry.size());
     // mmap the framebuffer
     mMmap.size = finfo.smem_len;
     uchar *data = (unsigned char *)mmap(0, mMmap.size, PROT_READ | PROT_WRITE, MAP_SHARED, mFbFd, 0);
@@ -383,42 +409,60 @@
         qErrnoWarning(errno, "Failed to mmap framebuffer");
         return false;
     }
-
-    mMmap.offset = geometry.y() * mBytesPerLine + geometry.x() * mDepth / 8;
+ 
+    //mMmap.offset = geometry.y() * mBytesPerLine + geometry.x() * mDepth / 8;
+	mMmap.offset = originalGeometry.y() * mBytesPerLine + originalGeometry.x() * mDepth / 8;
     mMmap.data = data + mMmap.offset;
-
+ 
     QFbScreen::initializeCompositor();
-    mFbScreenImage = QImage(mMmap.data, geometry.width(), geometry.height(), mBytesPerLine, mFormat);
-
+    //mFbScreenImage = QImage(mMmap.data, geometry.width(), geometry.height(), mBytesPerLine, mFormat);
+	mFbScreenImage = QImage(mMmap.data, originalGeometry.width(), originalGeometry.height(), mBytesPerLine, mFormat);
+ 
     mCursor = new QFbCursor(this);
-
+ 
     mTtyFd = openTtyDevice(ttyDevice);
     if (mTtyFd == -1)
         qErrnoWarning(errno, "Failed to open tty");
-
+ 
     switchToGraphicsMode(mTtyFd, doSwitchToGraphicsMode, &mOldTtyMode);
     blankScreen(mFbFd, false);
-
+ 
     return true;
 }
-
+ 
 QRegion QLinuxFbScreen::doRedraw()
 {
     QRegion touched = QFbScreen::doRedraw();
-
+ 
     if (touched.isEmpty())
         return touched;
-
+ 
     if (!mBlitter)
         mBlitter = new QPainter(&mFbScreenImage);
-
+ 
+	const QVector<QRect> rects = touched.rects();
     mBlitter->setCompositionMode(QPainter::CompositionMode_Source);
-    for (const QRect &rect : touched)
-        mBlitter->drawImage(rect, mScreenImage, rect);
-
+	for (int i = 0; i < rects.size(); ++i)
+	{
+		if( 90 == mRotation || 270 == mRotation )
+        {
+			mBlitter->translate(mGeometry.height()/2, mGeometry.width()/2);
+        }
+        else if( 180 == mRotation )
+        {
+            mBlitter->translate(mGeometry.width()/2, mGeometry.height()/2);
+        }
+        if( mRotation != 0 )
+        {
+            mBlitter->rotate(mRotation);
+            mBlitter->translate(-mGeometry.width()/2, -mGeometry.height()/2);
+        }
+        mBlitter->drawImage(rects[i], mScreenImage, rects[i]);
+		mBlitter->resetTransform();
+    }
     return touched;
 }
-
+ 
 // grabWindow() grabs "from the screen" not from the backingstores.
 // In linuxfb's case it will also include the mouse cursor.
 QPixmap QLinuxFbScreen::grabWindow(WId wid, int x, int y, int width, int height) const
@@ -430,7 +474,7 @@
             height = mFbScreenImage.height() - y;
         return QPixmap::fromImage(mFbScreenImage).copy(x, y, width, height);
     }
-
+ 
     QFbWindow *window = windowForId(wid);
     if (window) {
         const QRect geom = window->geometry();
@@ -442,9 +486,9 @@
         rect &= window->geometry();
         return QPixmap::fromImage(mFbScreenImage).copy(rect);
     }
-
+ 
     return QPixmap();
 }
-
+ 
 QT_END_NAMESPACE
-
+ 

四.Qt运行脚本配置

//触摸翻转
 export QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS=/dev/input/event$i:rotate=180
 //界面翻转
 export QT_QPA_PLATFORM=linuxfb:tty=/dev/fb0:rotation=180

  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值