在Hi3531上运行QT, 并对 mpp/sample/hifb/sample_hifb.c 修改

想用hi3531做Qt的开发,网上有相关的资料,但是解释就没那么清楚了,总结一下给大家分享.首先是网上已经有的文章.

http://blog.sina.com.cn/s/blog_48fba8050100y5yl.html

最近本人想要在Hi3531平台上运行QT,故有一些心得,写在这里与大家分享一下:

1.首先运行sample中的sample_hifb,以便打开fb0;但是需要对代码做一些修改:
将main函数中的 pthread_create(&phifb0,0,SAMPLE_HIFB_REFRESH,(void *)(&stInfo0));
改成 pthread_create(&phifb0,0,SAMPLE_HIFB_PTHREAD_RunHiFB,(void *)(&stInfo0));

将SAMPLE_HIFB_PTHREAD_RunHiFB函数中的HI_BOOL g_bCompress = HI_TRUE;
改成 HI_BOOL g_bCompress = HI_FALSE;


bShow = HI_TRUE;
if (ioctl(pstInfo->fd, FBIOPUT_SHOW_HIFB, &bShow) < 0)
{
printf(“FBIOPUT_SHOW_HIFB failed!\n”);
munmap(pShowScreen, fix.smem_len);
return HI_NULL;
}
后面加上
if (pstInfo->ctrlkey == 0)
{
while(1)
sleep(5);
}
到此修改完毕,然后编译它。

2.接下来就可以试图在Hi3531上运行QT了,
现在终端运行hifb的demo:sample_hifb
然后运行QT的demo:qt/demos/chip/chip -qws
至此你就可以看到QT的demo程序出现在屏幕上了。
enjoy!

但是这时候qt 程序只显示在一个小方块上,还有其他鼠标和图片的干扰,分辨率也只有720P,而不是1080P.接下来我们做相应的修改,使其满足我们开发Qt程序的需要.

一、设置显存

在《HIFB开发指南》中讲到要给每个图形叠加层多大的显存。

2.2 参数设置
HiFB可配置其管理的叠加图形层物理显存的大小。物理显存大小决定了HiFB可使用
的最大物理显存和系统的可设置虚拟分辨率。在加载HiFB驱动时通过参数传递设置物
理显存大小,物理显存的大小一经设置就不会改变。
参数video
video=“hifb:vram0_size:xxx, vram1_size:xxx,…”
z 选项之间用逗号“,”隔开。
z 选项和选项值之间用冒号“:”隔开。
z 如果某个图层不配置物理显存大小,则系统默认分配为0。
z vram0_size ~ vram6_size分别对应于叠加图形层0 ~ 叠加图形层6。
其中,vramn_size:xxx表示对叠加图形层n配置xxx K字节的物理显存。
(1)对于FB标准模式,vramn_size和虚拟分辨率的关系如下:
Vramn_size * 1024 >= xres_virtual * yres_virtual * bpp;
其中:xres_virtual * yres_virtual是虚拟分辨率,bpp是每个像素所占字节数。
(2)对于FB扩展模式,各个图形层需要的内存大小取决于displaysize的大小、图层像
素格式以及刷新模式,具体关系如下:

vramn_size * 1024 >= displaywidth * displayHeight * bpp * BufferMode;
如:图形层0在1280720 分辨率、ARGB8888格式的2 buffer模式下需要的内存
vram0_size = 1280
72042 = 7200 K。
vramn_size必须是PAGE_SIZE(4K byte)的倍数,否则HiFB驱动强制将其设为PAGE_SIZE的
倍数,向上取整。

参数默认值
如果加载HiFB驱动时不带任何参数,则系统默认配置的参数值见下。
(1) Hi3531
video=“hifb:vram0_size:7200,vram1_size:7200,vram2_size:3240,vram3_size:3240,v
ram4_size:7200,vram5_size:128,vram6_size:128” softcursor=“off”

2.3 配置举例
配置HiFB管理叠加图形层的示例如下:
HiFB驱动的模块文件为hifb.ko。
z 配置HiFB管理一个叠加图形层。
如果只需要HiFB管理叠加图形层0,且最大虚拟分辨率为720 x 576,用到的象素
格式为ARGB1555,则叠加图形层0需要的最小显存为720 x 576 x 2 = 829440 =
810K,配置参数如下:
insmod hifb.ko video=“hifb:vram0_size:810, vram2_size:0”。
如果采用的是double buffer的方式,则需要乘以2,即:
insmod hifb.ko video=“hifb:vram0_size:1620, vram2_size:0”。
z 配置HiFB管理多个叠加图形层。
如果需要HiFB管理叠加图形层0和叠加图形层1两个叠加层,且最大虚拟分辨率
为720 x 576,用到的像素格式为ARGB1555,则两个叠加层需要的最小显存都为
720 x 576 x 2 = 829440 = 810K,配置参数如下:
insmod hifb.ko video=“hifb:vram0_size:810, vram1_size: 810”

我使用的是fb0设备,分辨率为1080P=19201080, 19201080=2073600=2025k 这个应该是最小的内存数,我在 load3531中设置的参数为

insmod hifb.ko video=“hifb:vram0_size:20000,vram1_size:7200,vram2_size:3240,vram3_size:3240,
vram4_size:7200,vram5_size:128,vram6_size:128” softcursor=“off” u32VcmpBufNum=2
apszLayerMmzNames=“mmzname0”,“mmzname1”,“graphics”,“mmzname0”

hifb:vram0_size:20000,20M肯定够了。

二、打开HDMI接口,设置屏幕分辨率、屏幕起始坐标,透明度等

下面修改 sample_hifb.c 文件.里面有打开HDMI接口,设置屏幕分辨率、屏幕起始坐标等

参考文档: 《HiFB 开发指南》,《HiFB API参考》,《HiMPP 媒体处理软件开发参考》

  1. main 函数

VO_PUB_ATTR_S
【说明】
定义视频输出公共属性结构体。
【定义】
typedef struct hiVO_PUB_ATTR_S
{
HI_U32 u32BgColor; /* 设备背景色RGB表示*/
VO_INTF_TYPE_E enIntfType; /* Vo 接口类型*/
VO_INTF_SYNC_E enIntfSync; /* Vo接口时序类型*/
VO_SYNC_INFO_S stSyncInfo; /* Vo接口时序信息*/
HI_BOOL bDoubleFrame; /* 是否需要倍帧*/
} VO_PUB_ATTR_S;

u32BgColor 设备背景色,表示方法RGB888。

分辨率修改为1080P,这个最后才找到。

stPubAttr.enIntfSync = VO_OUTPUT_1080P50;

只用一个线程phifb0设置屏幕分辨率和phifb1设置画布起始点 就行了,所以可以把phifb2 的pthread_create, pthread_join 函数注释掉。线程0的参数如下

/*start hifb */
stInfo0.layer = 0;
stInfo0.fd = -1;
stInfo0.ctrlkey = 0;

pthread_create(&phifb0,0,SAMPLE_HIFB_REFRESH,(void *)(&stInfo0));

  1. 函数HI_VOID *SAMPLE_HIFB_REFRESH(void *pData) 里包含了设置屏幕分辨率的部分.先用FBIOGET_VSCREENINFO:获取屏幕可变信息,再用 FBIOPUT_VSCREENINFO:设置屏幕可变信息 。

s32Ret = ioctl(pstInfo->fd, FBIOGET_VSCREENINFO, &stVarInfo);
if(s32Ret < 0)
{
printf(“GET_VSCREENINFO failed!\n”);
return HI_NULL;
}

if (ioctl(pstInfo->fd, FBIOPUT_SCREEN_ORIGIN_HIFB, &stPoint) < 0)
{
    printf("set screen original show position failed!\n");
    return HI_NULL;
}

//slq
maxW = 1920;
maxH = 1080;

stVarInfo.xres = stVarInfo.xres_virtual = maxW;
stVarInfo.yres = stVarInfo.yres_virtual = maxH;
s32Ret = ioctl(pstInfo->fd, FBIOPUT_VSCREENINFO, &stVarInfo);
if(s32Ret < 0)

{
printf(“PUT_VSCREENINFO failed!\n”);
return HI_NULL;
}
else
{
printf(“PUT_VSCREENINFO success!\n”);
}

缓存方式选择,有无缓存,单缓存,双缓存

switch (pstInfo->ctrlkey)

{
case 0 :
{
stLayerInfo.BufMode = HIFB_LAYER_BUF_ONE;
stLayerInfo.u32Mask = HIFB_LAYERMASK_BUFMODE;
break;
}

case 1 :
{
stLayerInfo.BufMode = HIFB_LAYER_BUF_DOUBLE;
stLayerInfo.u32Mask = HIFB_LAYERMASK_BUFMODE;
break;
}

default:
{
stLayerInfo.BufMode = HIFB_LAYER_BUF_NONE;
stLayerInfo.u32Mask = HIFB_LAYERMASK_BUFMODE;
}

}

这部分不知道干啥的,应该是内存计算之类的吧,反正里面的1280,720改成 1920,1080不会错

for (y = 358; y < 362; y++)
{
for (x = 0; x < 1920; x++)
{
*(pBuf + y * maxW + x) = HIFB_RED_1555;
}
}
for (y = 0; y < 1080; y++)
{
for (x = 638; x < 642; x++)
{
*(pBuf + y * maxW + x) = HIFB_RED_1555;
}
}

我的主函数调用时,pstInfo->ctrlkey =0,所以只用修改 case 0 就可以了,虚拟宽度,高度和真实宽度,高度都设为1920*1080

switch(pstInfo->ctrlkey)
{
case 0:
{
//slq
//window width and height

        var.xres_virtual = 1920; 
        var.yres_virtual = 1080;
        var.xres = 1920;
        var.yres = 1080;
    }
    break;
    
    case 1:
    {
        var.xres_virtual = 100;
        var.yres_virtual = 100;
        var.xres = 220;
        var.yres = 200;
    }
    break;
    
    case 2:
    {
        var.xres_virtual = SAMPLE_VIR_SCREEN_WIDTH;
        var.yres_virtual = SAMPLE_VIR_SCREEN_HEIGHT;
        var.xres = SAMPLE_IMAGE_WIDTH;
        var.yres = SAMPLE_IMAGE_HEIGHT;
    }
    break;
    case 3:
    {
        var.xres_virtual = 48;
        var.yres_virtual = 48;
        var.xres = 48;
        var.yres = 48;
    }
    break;
    default:
    {
        var.xres_virtual = 98;
        var.yres_virtual = 128;
        var.xres = 98;
        var.yres = 64;
    }
}
  1. 函数HI_VOID *SAMPLE_HIFB_PTHREAD_RunHiFB(void *pData)里包含了设置屏幕起始坐标等

/* 2. set the screen original position */
switch(pstInfo->ctrlkey)
{
case 0:
{
//slq
// window start pos
stPoint.s32XPos= 0;
stPoint.s32YPos = 0;
}
break;

    case 1:
    {
        stPoint.s32XPos = 150;
        stPoint.s32YPos = 350;
    }
    break;
    
    case 2:
    {
        stPoint.s32XPos = 384;
        stPoint.s32YPos = 100;
    }
    break;
    case 3:
    {
        stPoint.s32XPos = 450;
        stPoint.s32YPos = 150;
    }

break;
default:
{
stPoint.s32XPos = 0;
stPoint.s32YPos = 0;
}
}

设置 alpha 透明度, 修改 stAlpha.u8GlobalAlpha = 0xff; 即可.

/* 3.set alpha */
stAlpha.bAlphaEnable = HI_TRUE;
stAlpha.bAlphaChannel = HI_TRUE;
stAlpha.u8Alpha0 = 0xff;
stAlpha.u8Alpha1 = 0xff;

//slq
//set transparent 
stAlpha.u8GlobalAlpha = 0xff;




if (ioctl(pstInfo->fd, FBIOPUT_ALPHA_HIFB,  &stAlpha) < 0) 
{    
    printf("Set alpha failed!\n");
    close(pstInfo->fd);
    return HI_NULL;
}    
if(pstInfo->layer == HIFB_LAYER_CURSOR_0 || pstInfo->layer == HIFB_LAYER_CURSOR_1)
{     
  stColorKey.bKeyEnable = HI_TRUE;
  stColorKey.u32Key = 0x0; 
  if (ioctl(pstInfo->fd, FBIOPUT_COLORKEY_HIFB, &stColorKey) < 0) 
  {    
    printf("FBIOPUT_COLORKEY_HIFB!\n");
    close(pstInfo->fd);
    return HI_NULL;
  }    
}    

在上述工作完成后

退出编辑,make后在板子上运行,屏幕为绿色,分辨率设置为1920*1080

./sample_hifb

tw2865 0x50 set to PAL mode ok!
tw2865 0x54 set to PAL mode ok!
tw2865 0x52 set to PAL mode ok!
tw2865 0x56 set to PAL mode ok!
u32Width:1920, u32Square:2
HDMI start success.
PUT_VSCREENINFO success!
expected:two red line!

程序运行一会就会自动结束,为了不让其自动结束,在上述工作后添加如下代码使程序一直运行,比如在设置好屏幕起始坐标后

//slq
if (pstInfo->ctrlkey == 0)
{
while(1)
sleep(5);
}

在后台运行 sample_hifb程序,便可再运行Qt 程序了

./sample_hifb &

tw2865 0x50 set to PAL mode ok!
tw2865 0x54 set to PAL mode ok!
tw2865 0x52 set to PAL mode ok!
tw2865 0x56 set to PAL mode ok!
u32Width:1920, u32Square:2
HDMI start success.
PUT_VSCREENINFO success!
expected:two red line!

发布了224 篇原创文章 · 获赞 14 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_43248127/article/details/104709905