想用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 = 128072042 = 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 媒體處理軟件開發參考》
- 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));
- 函數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;
}
}
- 函數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!