Enable linuxfb double buffering with Qt?

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 
已解决

Enable linuxfb double buffering with Qt?

跳至解决方案
8,493 次查看
chris_f
Contributor V

I'm running QML code using Qt5.8 on an iMX6ULL EVK with the 2D renderer back end. The system doesn't appear to use double buffering for the frame buffer so animations suffer with very bad image tearing (half written images being displayed). From what I can gather, I need to set up double buffering for the linuxfb itself and also modify the Qt Base qlinuxfbscreen.cpp code to use it.

Is that right? It seems strange that this hasn't been done before. The iMX6ULL is quite capable of simple animations from a processor perspective but if the frame buffer doesn't implement double buffering it's always going to look terrible.

标签 (3)
标记 (2)
1 解答
5,935 次查看
chris_f
Contributor V

The FB driver initialises to a 32MB video buffer irrespective of screen size - go resource efficiency.

It also initailises to a yres_virtual (the pannable size) equal to yres (the actual size). In order to pan the display, you need to set a larger yres_virtual value.

    struct fb_var_screeninfo vinfo;
    if (ioctl(fd, FBIOGET_VSCREENINFO, &vinfo)) {
        printf("Error reading variable screen information.\n");
    }
    vinfo.yres_virtual=vinfo.yres*2;
    if (ioctl(fd, FBIOPUT_VSCREENINFO, &vinfo)) {
        printf("Error putting variable screen information\n");
    }
    vinfo.yoffset=vinfo.yres;
    if (ioctl(fd, FBIOPAN_DISPLAY, &vinfo)) {
        printf("Error panning display.\n");
    }

I can now swap between the two panned display positions so adding double buffering to the Qt code should be fairly easy.

在原帖中查看解决方案

0 项奖励
回复
12 回复数
5,935 次查看
cilymo
Contributor I

Hi, Cris_f:

      Can you upload your Qt qlinuxfbscreen.cpp you solved the prolem ? I think i got the same problem. Thanks.

0 项奖励
回复
5,935 次查看
marius_grigoras
NXP Employee
NXP Employee

Hi,

I don't have experience with Qt, but using export FB_MULTI_BUFFER=2 in linux should work for enabling double buffer. 

If tearing is still present, you can use also triple buffering, using export FB_MULTI_BUFFER=3.

Please make a try,

Marius

5,935 次查看
chris_f
Contributor V

Thanks Marius, I'll give it a go.

0 项奖励
回复
5,935 次查看
chris_f
Contributor V

I tried export FB_MULTI_BUFFER=2 in the shell before running my executable (the same way I set the Qt variables QT_QPA_PLATFORM=linuxfb etc.) but it had no effect. I also tried using setenv under uboot but this didn't change anything either.

Which is the right way to export FB_MULTI_BUFFER=2?

0 项奖励
回复
5,935 次查看
marius_grigoras
NXP Employee
NXP Employee

Seems FB_MULTI_BUFFER variable is used only at galcore.ko level (linux kernel module for GPU driver). And from your use case, mostly the code that handles the buffering resides in the application and not in the driver. 

Hopefully someone with Qt knowledge will respond ASAP.

Thank you,

Marius

0 项奖励
回复
5,935 次查看
gary_bisson
Senior Contributor III

Hi Marius,

Yes FB_MULTI_BUFFER only applies to Galcore and Chris is using a i.MX6ULL which doesn't have any GPU so it won't help.

The FB driver does support FBIOPAN_DISPLAY so the question is how to make sure Qt Quick 2D renderer uses it.

Regards,

Gary

0 项奖励
回复
5,935 次查看
chris_f
Contributor V

Another clue! Thanks Gary. I'm getting no responses yet from the Qt forum/IRC/mailing list but am slowly getting to grips with bits of the Qt source so I'll start looking for FBIOPAN_DISPLAY references.

0 项奖励
回复
5,935 次查看
chris_f
Contributor V

I added some debug code to qlinuxfbscreen. cpp to see what the imx driver was returning.

Here's the relevant code:

mDepth = determineDepth(vinfo);
mBytesPerLine = finfo.line_length;
QRect geometry = determineGeometry(vinfo, userGeometry);
mGeometry = QRect(QPoint(0, 0), geometry.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;
}

qDebug() << "QLinuxFbScreen::initialize()";
qDebug() << "mBytesPerLine: " << mBytesPerLine;
qDebug() << "mMmap.size: " << mMmap.size;
qDebug() << "mGeometry: " << mGeometry;
qDebug() << "mPhysicalSize: " << mPhysicalSize;

and here's the ouput:

QLinuxFbScreen::initialize()
mBytesPerLine: 1280
mMmap.size: 33554432
mGeometry: QRect(0,0 320x480)
mPhysicalSize: QSizeF(81, 122)

I don't know what mPhysicalSize is yet. mBytesPerLine is fine as is mGeometry. The size_t returned by the FB driver though is big enough for more than 54 screens!!! Probably a bit bigger than we need. This looks to be like a problem with the imx driver but it's not the reason that I'm not getting double buffering. That doesn't seem to me to be implemented in Qt5.8.

0 项奖励
回复
5,935 次查看
chris_f
Contributor V

... but the FB driver returns -1 when I try to set a yoffset ...

0 项奖励
回复
5,936 次查看
chris_f
Contributor V

The FB driver initialises to a 32MB video buffer irrespective of screen size - go resource efficiency.

It also initailises to a yres_virtual (the pannable size) equal to yres (the actual size). In order to pan the display, you need to set a larger yres_virtual value.

    struct fb_var_screeninfo vinfo;
    if (ioctl(fd, FBIOGET_VSCREENINFO, &vinfo)) {
        printf("Error reading variable screen information.\n");
    }
    vinfo.yres_virtual=vinfo.yres*2;
    if (ioctl(fd, FBIOPUT_VSCREENINFO, &vinfo)) {
        printf("Error putting variable screen information\n");
    }
    vinfo.yoffset=vinfo.yres;
    if (ioctl(fd, FBIOPAN_DISPLAY, &vinfo)) {
        printf("Error panning display.\n");
    }

I can now swap between the two panned display positions so adding double buffering to the Qt code should be fairly easy.

0 项奖励
回复
5,935 次查看
chris_f
Contributor V

"Hopefully someone with Qt knowledge will respond ASAP." ... I hope so too. I'm getting no replies on the qt forums or IRC.

0 项奖励
回复
4,926 次查看
chentuo
Contributor I

Did you finally solve this problem? Thanks.

0 项奖励
回复