QT5.12.3 英伟达 TX2 移植 (支持电容屏)

一、tslib移植
1. 从https://github.com/libts/tslib/releases下载tslib最新源码 ,并解压
依次执行以下命令
#./autogen.sh
#echo "ac_cv_func_malloc_0_nonnull=yes" >arm-linux.cache
#CC=aarch64-linux-gnu-gcc ./configure --host=arm-linux --prefix=/opt/Qt5.12.3/tslib-1.20/tx2install --cache-file=arm-linux.cache
make && make install
2. 修改安装目录tx2install/etc/ts.conf
# module_raw input 
改为: 
module_raw input

二、QT5.12.3 移植
1.http://download.qt.io/archive/qt/5.12/5.12.3/single/ 下载 qt-everywhere-src-5.12.3.tar.xz
  并解压
  #xz -d qt-everywhere-src-5.12.3.tar.xz
  #tar xvz qt-everywhere-src-5.12.3.tar
2.修改qtbase/mkspecs/linux-arm-gnueabi-g++/qmake.conf
MAKEFILE_GENERATOR      = UNIX
CONFIG                 += incremental
QMAKE_INCREMENTAL_STYLE = sublib
QT_QPA_DEFAULT_PLATFORM = linuxfb:fb=/dev/fb0

QMAKE_CFLAGS_RELEASE   += -O2
QMAKE_CXXFLAGS_RELEASE += -O2
# modifications to g++.conf
QMAKE_CC                = aarch64-linux-gnu-gcc
QMAKE_CXX               = aarch64-linux-gnu-g++
QMAKE_LINK              = aarch64-linux-gnu-g++
QMAKE_LINK_SHLIB        = aarch64-linux-gnu-g++

# modifications to linux.conf
QMAKE_AR                = aarch64-linux-gnu-ar cqs
QMAKE_OBJCOPY           = aarch64-linux-gnu-objcopy
QMAKE_NM                = aarch64-linux-gnu-nm -P
QMAKE_STRIP             = aarch64-linux-gnu-strip

3.配置 创建myconfiure文件,并且设置未可执行
#touch myconfigure
#chmod +x myconfigure
文件内容
./configure -prefix ./tx2install \
-release -opensource -make libs -xplatform linux-arm-gnueabi-g++ \
-optimized-qmake -pch -qt-libjpeg -qt-zlib -no-opengl -skip qt3d \
-skip qtcanvas3d -skip qtpurchasing -no-sse2 -no-openssl -no-cups \
-no-glib -no-iconv -nomake examples -nomake tools -skip qtvirtualkeyboard \
-force-asserts -no-evdev -no-mtdev \
-tslib \
-I/opt/Qt5.12.3/tslib-1.20/tx2install/include \
-L/opt/Qt5.12.3/tslib-1.20/tx2install/lib

使用tslib 时候必须加上-no-evdev -no-mtdev ,evdev本来支持多点触摸则与tslib造成冲突, LCD触摸可能出现坐标错误情况

4. 修改 qtbase/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp 及 qlinuxfbscreen.h(因我的LCD是MIPI 接口的竖屏,需要更改为横屏,内核默认RGB 和LCD确实BGR)

qlinuxfbscreen.h

private:
    QStringList mArgs;
    int mFbFd;
    int mTtyFd;
    int mRotation;
    QImage mFbScreenImage;
    int mBytesPerLine;
    int mOldTtyMode;
    struct {
        uchar *data;
        int offset, size;
    } mMmap;
    QPainter *mBlitter;
    bool mSwapRgb;

qlinuxfbscreen.cpp

#include <linux/fb.h>

QT_BEGIN_NAMESPACE
typedef struct {
    QImage::Format format;
    bool swapRgb;
} FbFormat;

static int openFramebufferDevice(const QString &dev)

 

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 FbFormat determineFormat(const fb_var_screeninfo &info, int depth)
{
    const fb_bitfield rgba[4] = { info.red, info.green,
                                  info.blue, info.transp };
    FbFormat fbFormat;
    fbFormat.format = QImage::Format_Invalid;
    fbFormat.swapRgb = false;
    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) {
            fbFormat.format = QImage::Format_ARGB32;
        } else if (memcmp(rgba, argb8888, 3 * sizeof(fb_bitfield)) == 0) {
            fbFormat.format = QImage::Format_RGB32;
        } else if (memcmp(rgba, abgr8888, 3 * sizeof(fb_bitfield)) == 0) {
            fbFormat.format = QImage::Format_RGB32;
            fbFormat.swapRgb = true;
            // 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) {
            fbFormat.format = QImage::Format_RGB888;
        } else if (memcmp(rgba, bgr888, 3 * sizeof(fb_bitfield)) == 0) {
            fbFormat.format = QImage::Format_RGB888;
            fbFormat.swapRgb = true;
            // 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)
            fbFormat.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) {
            fbFormat.format = QImage::Format_RGB16;
        } else if (memcmp(rgba, bgr565, 3 * sizeof(fb_bitfield)) == 0) {
            fbFormat.format = QImage::Format_RGB16;
            fbFormat.swapRgb = true;
            // 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) {
            fbFormat.format = QImage::Format_RGB555;
        } else if (memcmp(rgba, bgr1555, 3 * sizeof(fb_bitfield)) == 0) {
            fbFormat.format = QImage::Format_RGB555;
            fbFormat.swapRgb = true;
            // 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)
            fbFormat.format = QImage::Format_RGB444;
        break;
    }
    case 8:
        break;
    case 1:
        fbFormat.format = QImage::Format_Mono; //###: LSB???
        break;
    default:
        break;
    }
    return fbFormat;
}

static int openTtyDevice(const QString &device)

 

QLinuxFbScreen::QLinuxFbScreen(const QStringList &args)
    : mArgs(args), mFbFd(-1), mTtyFd(-1), mBlitter(0),mRotation(90),mSwapRgb(false)
{
    mMmap.data = 0;
}

 

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+)"));
    
    QRegularExpression rotationRx(QLatin1String("rotation=(0|90|180|270)"));
    QString fbDevice, ttyDevice;
    QSize userMmSize;
    QRect userGeometry;
    bool doSwitchToGraphicsMode = true;

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);
        else if (arg.contains(rotationRx, &match))
            mRotation = match.captured(1).toInt();

    }

 

 


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

    QRect originalGeometry = geometry;
    if( 90 == mRotation  || 270 == mRotation )
    {
        int tmp = geometry.width();
        geometry.setWidth(geometry.height());
        geometry.setHeight(tmp);
    }


    mGeometry = QRect(QPoint(0, 0), geometry.size());
    FbFormat fbFormat = determineFormat(vinfo, mDepth);
    mFormat = fbFormat.format;
    mSwapRgb = fbFormat.swapRgb;

    

    //   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);

 

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

        
        if (mSwapRgb) {
            mBlitter->drawImage(rects[i], mScreenImage.rgbSwapped(),rects[i]);
        }
        else {
            mBlitter->drawImage(rects[i], mScreenImage, rects[i]);
        }        

    mBlitter->resetTransform();


    }
    return touched;
}

 

 

5.编译
     make -j4 && make install
     编译完成后,在源码根目录./tx2install目录下生成TX2 QT库
6.移植库到TX2根文件系统
    6.1文件系统默认自带的QT库删除掉 
    #rm -rf  /usr/lib/aarch64-linux-gnu/libQt*
6.2拷贝移植后的QT 到 TX2 根文件系统
    cp -arf      ./tx2install/*        /usr/local/Qt5.12.3/
6.3增加环境变量(根据具体的屏幕分辨率 尺寸进行设置)

export QTEDIR=/usr/local/Qt5.12.3
export QT_QPA_FONTDIR=$QTEDIR/lib/fonts
export QT_QPA_PLATFORM_PLUGIN_PATH=$QTEDIR/plugins
export QT_QPA_PLATFORM=linuxfb:fb=/dev/fb0:size=720x1280:mmSize=720x1280:offset==0x0:tty=/dev/tty1
export QWS_DISPLAY=LinuxFB:mmWidth68:mmHeight121:0

export TSLIB_ROOT=/usr/local/tslib1.20
export TSLIB_TSDEVICE=/dev/input/event0
export TSLIB_TSEVENTTYPE=input
export TSLIB_CALIBFILE=$TSLIB_ROOT/etc/pointercal    
export TSLIB_CONFFILE=$TSLIB_ROOT/etc/ts.conf  
export TSLIB_PLUGINDIR=$TSLIB_ROOT/lib/ts  
export TSLIB_FBDEVICE=/dev/fb0   
export TSLIB_CONSOLEDEVICE=none     
export QT_QPA_GENERIC_PLUGINS=tslib:$TSLIB_TSDEVICE

export LD_LIBRARY_PATH=/usr/local/Qt5.12.3/lib:$TSLIB_ROOT/lib
export LD_PRELOAD=$TSLIB_ROOT/lib/libts.so:$QTEDIR/plugins/platforms/libqlinuxfb.so

6.4将字体文件拷贝至TX2文件系统
    /usr/local/Qt5.12.3/lib/fonts
6.5增加QT库搜索路径
在 /etc/ld.so.conf 添加/usr/local/Qt5.12.3/lib /usr/local/tslib1.20/lib
include /etc/ld.so.conf.d/*.conf
/usr/local/Qt5.12.3/lib
/usr/local/tslib1.20/lib

7.主机编译QT 程序
1.添加qmake 执行路径
在 /etc/environment添加qmake的路径至PATH   /opt/Qt5.12.3/qt-everywhere-src-5.12.3/tx2install/bin/
2.设置QMAKESPEC环境变量
export QMAKESPEC=/opt/Qt5.12.3/qt-everywhere-src-5.12.3/tx2install/mkspecs/linux-arm-gnueabi-g++/
3.执行qmake 创建makefile,编译ARM端运行的程序
qmake -project QT+=widgets 创建 .pro工程文件
qmake -o Makefile 
make
若需要旋转LCD
export QT_QPA_PLATFORM=linuxfb:fb=/dev/fb0:size=720x1280:mmSize=720x1280:offset=0x0:tty=/dev/tty1:rotation=90
或者运行程序时加入参数: ./app -platform linuxfb:fb=/dev/fb0:rotatio=90

运行时 需要在 /etc/rc.local中添加以下代码
chmod -x /usr/sbin/lightdm
systemctl disable lightdm.service
echo 2 > /sys/class/graphics/fb0/blank
echo 1 > /sys/class/graphics/fb0/blank
echo 0 > /sys/class/graphics/fb0/blank

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值