rk3576(2)之添加qt以及添加linux旋转补丁

1、简介

使用环境rk3576+kernel-6.1+buildroot 2024.02

使用的SDK是野火的LubanCat_Linux_Generic_Full_SDK_20250826.tgz

因为我上文修改的设备树主要就是为了服务于qt,但是qt一开始并没有被编译,所以自己需要去修改一下

qt是buildroot的事情,其中

qt的源码存放在buildroot/dl/qt5base/目录下,

qt的补丁存在在buildroot/package/qt5/qt5base

这个两个目录切记,等会需要修改一下qt的源码

2、配置Qt

一切参数都是默认的,比如交叉编译选择的是内部编译器

配置路径在

复制代码
Target packages 
	-> Graphic libraries and applications (graphic/text) 
		-> Qt5

先把Qt5勾选起来然后进入,就可以配置qt了,我的配置有:

复制代码
qt5base
gui module
	-> widgets module
	-> OpenGL support 
	-> opengl module
linuxfb support
eglfs support
harfbuzz support
GIF support
JPEG support
PNG support
Enable Tslib support
qt5charts
qt5wayland 
Enable compositor (experimental) 

注意:其实linux、eglfs、wayland选择一个就行,但是我在试验阶段,我就全部勾选每个都试了一下

修改完以后执行

复制代码
make savedefconfig

将修改提交,不然以后忘记或者恢复不了

复制代码
lubancat@lubancat-vm:~/Temp/buildroot$ make savedefconfig
  GEN     /home/lubancat/Temp/buildroot/output/rockchip_rk3576_lubancat/Makefile
lubancat@lubancat-vm:~/Temp/buildroot$ git status
当前不在任何分支上。
尚未暂存以备提交的变更:
  (使用 "git add <文件>..." 更新要提交的内容)
  (使用 "git restore <文件>..." 丢弃工作区的改动)
	修改:     configs/rockchip_rk3576_lubancat_defconfig

修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
lubancat@lubancat-vm:~/Temp/buildroot$ git add configs/rockchip_rk3576_lubancat_defconfig
lubancat@lubancat-vm:~/Temp/buildroot$ git commit -m "add qt"
[分离头指针 61ac05a4] add qt
 1 file changed, 197 insertions(+), 33 deletions(-)
 rewrite configs/rockchip_rk3576_lubancat_defconfig (74%)
lubancat@lubancat-vm:~/Temp/buildroot$ git log
commit 61ac05a44e85e7b04e7406944e751ba129bc918e (HEAD)
Author: lubancat <lubancat>
Date:   Sun Mar 8 00:39:08 2026 +0800

    add qt

commit b2460d5cf8d810814815f4df0826d32fe13da99e (grafted, m/linux)
Author: hejiawencc <hjw0415@outlook.com>
Date:   Fri Mar 7 15:32:29 2025 +0800

    configs 添加LubanCat rk3562板卡配置文件
lubancat@lubancat-vm:~/Temp/buildroot$ 

3、添加补丁

有一个需求旋转屏幕,但是linuxfb不支持旋转,所以需要改一下源码,其中你不能够直接修改源码,因为源码的源码是一开始下载的压缩包,然后后面编译的代码是生成的,你可以理解为结果,你在结果上修改是不起作用的,你看路径是在output里的

复制代码
rk3576_buildroot_sdk
	->buildroot
		->output
			->rockchip_rk3576_lubancat
				->build
				    ->qt5base-da6e958319e95fe564d3b30c931492dd666bfaff
				        ->src
				            ->plugins
				                ->platforms
				                    ->linuxfb
				                        ->qlinuxfbscreen.cpp

所以你想要正确的修改办法:

1、你要么你把buildroot/dl/qt5base/目录下的源码解压修改后再压缩,但是这个肯定是不可取的,因为随意的修改源码肯定不是一个好的解决方案

2、你复制源码出来,修改,然后与老的源码对比生成patch,再把patch放到buildroot/package/qt5/qt5base

3.1、修改qlinuxfbscreen.cpp和qlinuxfbscreen.h

修改的源码是复制网上的。

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>

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

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 <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;
    }

    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)  // modify by immortal
 : 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)) {
        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 geometryTmp = geometry;
	if( 90 == mRotation  || 270 == mRotation )
    {
		int tmp = geometryTmp.width();
        geometryTmp.setWidth(geometryTmp.height());
        geometryTmp.setHeight(tmp);
    }
	// add by immortal end
	
    mGeometry = QRect(QPoint(0, 0), geometryTmp.size());
    mFormat = determineFormat(vinfo, mDepth);
    mPhysicalSize = determinePhysicalSize(vinfo, userMmSize, geometry.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.data = data + mMmap.offset;

    QFbScreen::initializeCompositor();
    mFbScreenImage = QImage(mMmap.data, geometry.width(), geometry.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);

    mBlitter->setCompositionMode(QPainter::CompositionMode_Source);
    for (const QRect &rect : touched)
	// add by immortal start		
	{
		if( mRotation != 0 ){
			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);
			}
			
			mBlitter->rotate(mRotation);
			mBlitter->translate(-mGeometry.width()/2, -mGeometry.height()/2);
		}
	// add by immortal end	
	
        mBlitter->drawImage(rect, mScreenImage, rect);
		
		// add by immortal start
		if( mRotation != 0 )
			mBlitter->resetTransform();
		// add by immortal end
    }
    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

3.2、使用diff命令生成patch

首先我的修改的目录是newQt5Src,未动的源码qtbase-da6e958319e95fe564d3b30c931492dd666bfaff

复制代码
lubancat@lubancat-vm:~/rk3576_buildroot_sdk/buildroot/temp$ ls
newQt5Src  qtbase-da6e958319e95fe564d3b30c931492dd666bfaff

diff -uNr qtbase-da6e958319e95fe564d3b30c931492dd666bfaff/ newQt5Src/ > 009-linuxfb-20260306.patch.patch

执行diff命令生成了patch,查看patch内容:

复制代码
diff -uNr qtbase-da6e958319e95fe564d3b30c931492dd666bfaff/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp newQt5Src/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp
--- qtbase-da6e958319e95fe564d3b30c931492dd666bfaff/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp	2023-06-09 22:30:54.000000000 +0800
+++ newQt5Src/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp	2026-03-06 13:44:49.160052290 +0800
@@ -287,7 +287,8 @@
 }
 
 QLinuxFbScreen::QLinuxFbScreen(const QStringList &args)
-    : mArgs(args), mFbFd(-1), mTtyFd(-1), mBlitter(0)
+// : mArgs(args), mFbFd(-1), mTtyFd(-1), mBlitter(0)  // modify by immortal
+ : mArgs(args), mFbFd(-1), mTtyFd(-1), mBlitter(0),mRotation(0)
 {
     mMmap.data = 0;
 }
@@ -313,6 +314,9 @@
     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;
@@ -334,6 +338,10 @@
             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()) {
@@ -372,9 +380,20 @@
     mDepth = determineDepth(vinfo);
     mBytesPerLine = finfo.line_length;
     QRect geometry = determineGeometry(vinfo, userGeometry);
+    
+    	// add by immortal start
+	QRect geometryTmp = geometry;
+	if( 90 == mRotation  || 270 == mRotation )
+    	{
+		int tmp = geometryTmp.width();
+        	geometryTmp.setWidth(geometryTmp.height());
+        	geometryTmp.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, geometryTmp.size());
 
     // mmap the framebuffer
     mMmap.size = finfo.smem_len;
@@ -414,8 +433,27 @@
 
     mBlitter->setCompositionMode(QPainter::CompositionMode_Source);
     for (const QRect &rect : touched)
+	// add by immortal start		
+	{
+		if( mRotation != 0 ){
+			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);
+			}
+			
+			mBlitter->rotate(mRotation);
+			mBlitter->translate(-mGeometry.width()/2, -mGeometry.height()/2);
+		}
+	// add by immortal end	
+	
         mBlitter->drawImage(rect, mScreenImage, rect);
-
+		
+	mBlitter->resetTransform();
+    }
     return touched;
 }
 
diff -uNr qtbase-da6e958319e95fe564d3b30c931492dd666bfaff/src/plugins/platforms/linuxfb/qlinuxfbscreen.h newQt5Src/src/plugins/platforms/linuxfb/qlinuxfbscreen.h
--- qtbase-da6e958319e95fe564d3b30c931492dd666bfaff/src/plugins/platforms/linuxfb/qlinuxfbscreen.h	2023-06-09 22:30:54.000000000 +0800
+++ newQt5Src/src/plugins/platforms/linuxfb/qlinuxfbscreen.h	2026-03-05 16:10:47.702042293 +0800
@@ -64,6 +64,9 @@
     QStringList mArgs;
     int mFbFd;
     int mTtyFd;
+	// add by immortal start
+	int mRotation;
+	// add by immortal end
 
     QImage mFbScreenImage;
     int mBytesPerLine;

注意注意,这个patch文件最好是生成的不要直接用网上的复制,不然就会有一点差别就会报错

3.3、将patch放到指定目录

复制代码
mv 009-linuxfb-20260306.patch.patch  ~/rk3576_buildroot_sdk/buildroot/package/qt5/qt5base/

4、编译,烧写运行

5、总结

这个qt的支持实在是方便的不行,而且编译好的镜像烧写后不需要自己再次复制库文件到板子上

学习了这个添加补丁的方法

但是这个linuxfb旋转其实不建议,第一原点有问题,旋转的效果不尽人意,然后就是执行所需要的时间更长了,要么使用weston+wayland,要么使用eglfs

相关推荐
Suifqwu7 小时前
rk3576(4)之buildroot添加package以及Qt程序开机自启
qt·buildroot·rk3576
peixiuhui1 个月前
G8701 RK3576 RealTime Linux 测试报告
linux·运维·边缘计算·rk3588·rk3576·rt-linux·实时内核
Industio_触觉智能1 个月前
解锁多路GMSL摄像头输入,基于瑞芯微RK3576的触觉智能硬件方案
瑞芯微·rk3576·ahd·gmsl·rk3576j·多路摄像头·gmsl解串
Industio_触觉智能2 个月前
触觉智能RK3576开发板OpenHarmony开源鸿蒙蓝牙BLE主机实现方案
蓝牙·openharmony·主机·ble·开源鸿蒙·rk3576·从机
Industio_触觉智能2 个月前
瑞芯微RK3576的MIPI CSI-2接口,4K视频输入与兼容实现技巧
开发板·核心板·瑞芯微·rk3576·触觉智能·mipi csi2·视频输入
peixiuhui2 个月前
突破边界!RK3576边缘计算网关:为工业智能注入“芯”动力
人工智能·物联网·边缘计算·rk3588·iot·rk3568·rk3576
peixiuhui2 个月前
OpenPLC与RK3576边缘计算网关中结合应用的技术案例与分析
人工智能·边缘计算·rk3588·rk3568·openplc·rk3576·g8701
peixiuhui2 个月前
RK3576加持的G8701边缘计算网关深度评测:工业级AIoT的终极解决方案
人工智能·边缘计算·rk3588·嵌入式开发·aiot·工业控制·rk3576
键来大师2 个月前
Android16 AP热点修改默认密码为12345678
android·framework·rk3576·android16