Linuxfb 旋转屏幕
关键词: git patch yocto linuxfb qt5.11.3
事情是这样的,在开发板上使用Qt,有个需求,要求应用能够旋转,适配不同的屏幕。
在eglfs,Wayland各种切换,当然也成功了,但是由于其他原因最终还是要使用Linuxfb。
由于Qt5的Linuxfb不支持旋转,所以需要自己去改显示插件驱动。
网上找了一下,只找到了一个5.4的patch,直接用用不了,所以就要只能自己来改源码,
生成patch,打patch。
我是用的是yocto来构建Qt SDK,然后使用的是imx官方的yocto工程,
就遇到一个问题qtbase的源码无法通过devtools获取,完全克隆的干净仓库也不行。。
所以我就只能照着yocto的patch来改一个可以用的patch,有点绕但是就是这么麻烦。。
主要内容:
使用imx官方yocto工程向Qt(版本5.11.3)源码打linufb旋转屏幕的补丁。
- 修改Linuxfb源码
- git 生成 patch
- yocto添加patch
- linudfb旋转屏幕
文档参考:
- 如何使用git 生成patch 和打入patch https://blog.csdn.net/liuhaomatou/article/details/54410361
最新地址: https://taotaodiy-yocto.readthedocs.io/en/latest/yocto/yocto_patch_linuxfb.html
修改后的 linuxfb 源码
Qt 版本为 5.11.3 与网上的patch内容有点不一样就照着改了一份。
下面是修改好的linuxfb源码,直接支持屏幕旋转。
#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() override;
QPixmap grabWindow(WId wid, int x, int y, int width, int height) const override;
QRegion doRedraw() override;
private:
QStringList mArgs;
int mFbFd;
int mTtyFd;
//添加内容
int mRotation;
//添加内容
QImage mFbScreenImage;
int mBytesPerLine;
int mOldTtyMode;
struct {
uchar *data;
int offset, size;
} mMmap;
QPainter *mBlitter;
};
QT_END_NAMESPACE
#endif // QLINUXFBSCREEN_H
#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) {
m