G2D主要功能:
1)旋轉(zhuǎn):支持90、180、270旋轉(zhuǎn);
2)scale:放縮;
3)鏡像反轉(zhuǎn):H / V;
4)透明疊加:實(shí)現(xiàn)兩個(gè)rgb圖片疊加;
5)格式轉(zhuǎn)換:yuv轉(zhuǎn)rgb等多種格式相互間轉(zhuǎn)換;
6)矩形填充,等諸多功能;
G2D配置
源碼目錄
tina-v853-docker/kernel/linux-4.9/drivers/char/sunxi_g2d
make kernel_menuconfig 配置
Device Drivers > Character devices > sunxi g2d driver

Device Tree 設(shè)備樹配置
sun8iw21p1.dtsi路徑:
tina-v853-docker/kernel/linux-4.9/arch/arm/boot/dts/sun8iw21p1.dtsi
g2d: g2d@05410000 {
compatible = "allwinner,sunxi-g2d";
reg = <0x0 0x05410000 0x0 0xbffff>;
interrupts = ;
clocks = <&clk_g2d>;
iommus = <&mmu_aw 3 1>;
status = "okay";
};
注:status 要設(shè)定為“okay” 狀態(tài)。
重新編譯內(nèi)核
使用燒錄工具PhoenixSuit 將編譯打包好的img鏡像燒錄到開發(fā)板。
adb shell 打開控制終端查看設(shè)備節(jié)點(diǎn)G2D:

通過G2D設(shè)備節(jié)點(diǎn)進(jìn)行操作
static int SampleG2d_G2dOpen(SAMPLE_G2D_CTX *p_g2d_ctx)
{
int ret = 0;
p_g2d_ctx->mG2dFd = open("/dev/g2d", O_RDWR, 0);
if (p_g2d_ctx->mG2dFd < 0)
? ?{
? ? ? ?aloge("fatal error! open /dev/g2d failed");
? ? ? ?ret = -1;
? ?}
? ?return ret;
}
G2D sample具體應(yīng)用
G2D sample目錄

進(jìn)行rotation,scale,格式轉(zhuǎn)換
具體實(shí)現(xiàn):將 nv21 格式的1920x1080圖轉(zhuǎn)換成rgb888 格式并放縮為640x360 大小。具體用到兩個(gè)功能,格式轉(zhuǎn)換和放縮。
首先根據(jù)1920x1080 nv21 格式以及 640x360 rgb888 格式申請(qǐng)?zhí)摂M地址空間以及轉(zhuǎn)換成物理地址(注意:g2d 轉(zhuǎn)換是在物理地址中完成的)
1920x1080 nv21 格式空間大?。ㄝ斎胛募?/strong>
Y 占 19201080 = 2073600 字節(jié)
UV 占 19201080 / 2 = 1036800 字節(jié)

640x360 rgb888 格式空間大小(輸出文件):
RGB 占 6403603 = 691200 字節(jié)
另外:虛擬地址轉(zhuǎn)換成物理地址使用如下函數(shù):
g2d_getPhyAddrByVirAddr()
申請(qǐng)?zhí)摂M空間并轉(zhuǎn)換成物理空間完整函數(shù)如下:
static int PrepareFrmBuff(SAMPLE_G2D_CTX *p_g2d_ctx)
{
SampleG2dConfig *pConfig = NULL;
unsigned int size = 0;
pConfig = &p_g2d_ctx->mConfigPara;
p_g2d_ctx->src_frm_info.frm_width = pConfig->mSrcWidth;
p_g2d_ctx->src_frm_info.frm_height = pConfig->mSrcHeight;
p_g2d_ctx->dst_frm_info.frm_width = pConfig->mDstWidth;
p_g2d_ctx->dst_frm_info.frm_height = pConfig->mDstHeight;
size = ALIGN(p_g2d_ctx->src_frm_info.frm_width, 16)*ALIGN(p_g2d_ctx->src_frm_info.frm_height, 16);
if(pConfig->mPicFormat == MM_PIXEL_FORMAT_YVU_SEMIPLANAR_420 || pConfig->mPicFormat == MM_PIXEL_FORMAT_YUV_SEMIPLANAR_420)
{
p_g2d_ctx->src_frm_info.p_vir_addr[0] = (void *)g2d_allocMem(size);
if(NULL == p_g2d_ctx->src_frm_info.p_vir_addr[0])
{
aloge("malloc_src_frm_y_mem_failed");
return -1;
}
p_g2d_ctx->src_frm_info.p_vir_addr[1] = (void *)g2d_allocMem(size/2);
if(NULL == p_g2d_ctx->src_frm_info.p_vir_addr[1])
{
g2d_freeMem(p_g2d_ctx->src_frm_info.p_vir_addr[0]);
aloge("malloc_src_frm_c_mem_failed");
return -1;
}
p_g2d_ctx->src_frm_info.p_phy_addr[0] = (void *)g2d_getPhyAddrByVirAddr(p_g2d_ctx->src_frm_info.p_vir_addr[0]);
p_g2d_ctx->src_frm_info.p_phy_addr[1] = (void *)g2d_getPhyAddrByVirAddr(p_g2d_ctx->src_frm_info.p_vir_addr[1]);
}
if(pConfig->mDstPicFormat == MM_PIXEL_FORMAT_RGB_888)
{
size = p_g2d_ctx->dst_frm_info.frm_width * p_g2d_ctx->dst_frm_info.frm_height * 3;
p_g2d_ctx->dst_frm_info.p_vir_addr[0] = (void *)g2d_allocMem(size);
if(NULL == p_g2d_ctx->dst_frm_info.p_vir_addr[0])
{
if(p_g2d_ctx->src_frm_info.p_vir_addr[0] != NULL)
{
g2d_freeMem(p_g2d_ctx->src_frm_info.p_vir_addr[0]);
}
if(p_g2d_ctx->src_frm_info.p_vir_addr[1] != NULL)
{
g2d_freeMem(p_g2d_ctx->src_frm_info.p_vir_addr[1]);
}
aloge("malloc_dst_frm_y_mem_failed");
return -1;
}
p_g2d_ctx->dst_frm_info.p_phy_addr[0] = (void *)g2d_getPhyAddrByVirAddr(p_g2d_ctx->dst_frm_info.p_vir_addr[0]);
}
return 0;
}
通過fopen 傳菜間兩個(gè)文件句柄,fd_in fd_out 用來(lái)操作輸入輸出兩個(gè)文件資源。
p_g2d_ctx->fd_in = fopen(p_g2d_ctx->mConfigPara.SrcFile,"r");
if(NULL == p_g2d_ctx->fd_in)
{
aloge("open src file failed");
ret = -1;
goto _err2;
}
fseek(p_g2d_ctx->fd_in, 0, SEEK_SET);
p_g2d_ctx->fd_out = fopen(p_g2d_ctx->mConfigPara.DstFile, "wb");
if (NULL == p_g2d_ctx->fd_out)
{
aloge("open out file failed");
ret = -1;
goto _err2;
}
fseek(p_g2d_ctx->fd_out, 0, SEEK_SET);
讀出 1920x1080 nv21 圖資放入 虛擬空間
read_len = p_g2d_ctx->src_frm_info.frm_width * p_g2d_ctx->src_frm_info.frm_height;
if(pConfig->mPicFormat == MM_PIXEL_FORMAT_YVU_SEMIPLANAR_420|| pConfig->mPicFormat == MM_PIXEL_FORMAT_YUV_SEMIPLANAR_420)
{
size1 = fread(p_g2d_ctx->src_frm_info.p_vir_addr[0] , 1, read_len, p_g2d_ctx->fd_in);
if(size1 != read_len)
{
aloge("read_y_data_frm_src_file_invalid");
}
size2 = fread(p_g2d_ctx->src_frm_info.p_vir_addr[1], 1, read_len /2, p_g2d_ctx->fd_in);
if(size2 != read_len/2)
{
aloge("read_c_data_frm_src_file_invalid");
}
fclose(p_g2d_ctx->fd_in);
g2d_flushCache((void *)p_g2d_ctx->src_frm_info.p_vir_addr[0], read_len);
g2d_flushCache((void *)p_g2d_ctx->src_frm_info.p_vir_addr[1], read_len/2);
}
打開g2d 初始化,并開始轉(zhuǎn)換
ret = SampleG2d_G2dOpen(p_g2d_ctx);
if (ret < 0)
? ?{
? ? ? ?aloge("fatal error! open /dev/g2d fail!");
? ? ? ?goto _err2;
? ?}
? ?ret = SampleG2d_G2dConvert(p_g2d_ctx);
? ?if (ret < 0)
? ?{
? ? ? ?aloge("fatal error! g2d convert fail!");
? ? ? ?goto _close_g2d;
? ?}
//具體轉(zhuǎn)化函數(shù):
static int SampleG2d_G2dConvert_scale(SAMPLE_G2D_CTX *p_g2d_ctx)
{
? ?int ret = 0;
? ?g2d_blt_h blit;
? ?g2d_fmt_enh eSrcFormat, eDstFormat;
? ?SampleG2dConfig *pConfig = NULL;
? ?pConfig = &p_g2d_ctx->mConfigPara;
ret = convert_PIXEL_FORMAT_E_to_g2d_fmt_enh(pConfig->mPicFormat, &eSrcFormat);
if(ret!=SUCCESS)
{
aloge("fatal error! src pixel format[0x%x] is invalid!", pConfig->mPicFormat);
return -1;
}
ret = convert_PIXEL_FORMAT_E_to_g2d_fmt_enh(pConfig->mDstPicFormat, &eDstFormat);
if(ret!=SUCCESS)
{
aloge("fatal error! dst pixel format[0x%x] is invalid!", pConfig->mPicFormat);
return -1;
}
//config blit
memset(&blit, 0, sizeof(g2d_blt_h));
if(0 != pConfig->mDstRotate)
{
aloge("fatal_err: rotation can't be performed when do scaling");
}
blit.flag_h = G2D_BLT_NONE_H; // angle rotation used
// switch(pConfig->mDstRotate)
// {
// case 0:
// blit.flag_h = G2D_BLT_NONE_H; //G2D_ROT_0, G2D_BLT_NONE_H
// break;
// case 90:
// blit.flag_h = G2D_ROT_90;
// break;
// case 180:
// blit.flag_h = G2D_ROT_180;
// break;
// case 270:
// blit.flag_h = G2D_ROT_270;
// break;
// default:
// aloge("fatal error! rotation[%d] is invalid!", pConfig->mDstRotate);
// blit.flag_h = G2D_BLT_NONE_H;
// break;
// }
//blit.src_image_h.bbuff = 1;
//blit.src_image_h.color = 0xff;
blit.src_image_h.format = eSrcFormat;
blit.src_image_h.laddr[0] = (unsigned int)p_g2d_ctx->src_frm_info.p_phy_addr[0];
blit.src_image_h.laddr[1] = (unsigned int)p_g2d_ctx->src_frm_info.p_phy_addr[1];
blit.src_image_h.laddr[2] = (unsigned int)p_g2d_ctx->src_frm_info.p_phy_addr[2];
//blit.src_image_h.haddr[] =
blit.src_image_h.width = p_g2d_ctx->src_frm_info.frm_width;
blit.src_image_h.height = p_g2d_ctx->src_frm_info.frm_height;
blit.src_image_h.align[0] = 0;
blit.src_image_h.align[1] = 0;
blit.src_image_h.align[2] = 0;
blit.src_image_h.clip_rect.x = pConfig->mSrcRectX;
blit.src_image_h.clip_rect.y = pConfig->mSrcRectY;
blit.src_image_h.clip_rect.w = pConfig->mSrcRectW;
blit.src_image_h.clip_rect.h = pConfig->mSrcRectH;
blit.src_image_h.gamut = G2D_BT601;
blit.src_image_h.bpremul = 0;
//blit.src_image_h.alpha = 0xff;
blit.src_image_h.mode = G2D_PIXEL_ALPHA; //G2D_PIXEL_ALPHA, G2D_GLOBAL_ALPHA
blit.src_image_h.fd = -1;
blit.src_image_h.use_phy_addr = 1;
//blit.dst_image_h.bbuff = 1;
//blit.dst_image_h.color = 0xff;
blit.dst_image_h.format = eDstFormat;
blit.dst_image_h.laddr[0] = (unsigned int)p_g2d_ctx->dst_frm_info.p_phy_addr[0];
blit.dst_image_h.laddr[1] = (unsigned int)p_g2d_ctx->dst_frm_info.p_phy_addr[1];
blit.dst_image_h.laddr[2] = (unsigned int)p_g2d_ctx->dst_frm_info.p_phy_addr[2];
//blit.dst_image_h.haddr[] =
blit.dst_image_h.width = p_g2d_ctx->dst_frm_info.frm_width;
blit.dst_image_h.height = p_g2d_ctx->dst_frm_info.frm_height;
blit.dst_image_h.align[0] = 0;
blit.dst_image_h.align[1] = 0;
blit.dst_image_h.align[2] = 0;
blit.dst_image_h.clip_rect.x = pConfig->mDstRectX;
blit.dst_image_h.clip_rect.y = pConfig->mDstRectY;
blit.dst_image_h.clip_rect.w = pConfig->mDstRectW;
blit.dst_image_h.clip_rect.h = pConfig->mDstRectH;
blit.dst_image_h.gamut = G2D_BT601;
blit.dst_image_h.bpremul = 0;
//blit.dst_image_h.alpha = 0xff;
blit.dst_image_h.mode = G2D_PIXEL_ALPHA; //G2D_PIXEL_ALPHA, G2D_GLOBAL_ALPHA
blit.dst_image_h.fd = -1;
blit.dst_image_h.use_phy_addr = 1;
ret = ioctl(p_g2d_ctx->mG2dFd, G2D_CMD_BITBLT_H, (unsigned long)&blit);
if(ret < 0)
? ?{
? ? ? ?aloge("fatal error! bit-block(image) transfer failed[%d]", ret);
? ? ? ?system("cd /sys/class/sunxi_dump;echo 0x14A8000,0x14A8100 > dump;cat dump");
}
return ret;
}
轉(zhuǎn)化完成后將640x360 rgb888 圖資通過fd_out句柄存儲(chǔ)起來(lái)
if(pConfig->mDstPicFormat == MM_PIXEL_FORMAT_RGB_888)
{
out_len = p_g2d_ctx->dst_frm_info.frm_width * p_g2d_ctx->dst_frm_info.frm_height *3;
g2d_flushCache((void *)p_g2d_ctx->dst_frm_info.p_vir_addr[0], out_len);
fwrite(p_g2d_ctx->dst_frm_info.p_vir_addr[0], 1, out_len, p_g2d_ctx->fd_out);
}
轉(zhuǎn)化步驟總結(jié)
通過步驟3中的模塊化分析,可以看出g2d 轉(zhuǎn)化大概分為一下步驟:
為打開 iomen 初始化;
為src以及dst圖資申請(qǐng)?zhí)摂M地址空間并轉(zhuǎn)換成物理地址空間;
將src圖資放入虛擬地址空間,然后自動(dòng)映射到物理地址空間;
打開g2d 設(shè)備節(jié)點(diǎn)進(jìn)行轉(zhuǎn)換(最重要的一環(huán),可以通過手冊(cè)分析具體怎么轉(zhuǎn)換的);
將轉(zhuǎn)換好的dst圖資保存起來(lái);
審核編輯:劉清
-
RGB
+關(guān)注
關(guān)注
4文章
820瀏覽量
61479 -
SRC
+關(guān)注
關(guān)注
0文章
63瀏覽量
18648 -
Shell
+關(guān)注
關(guān)注
1文章
373瀏覽量
25155 -
V850
+關(guān)注
關(guān)注
0文章
4瀏覽量
7205 -
ADB驅(qū)動(dòng)
+關(guān)注
關(guān)注
0文章
13瀏覽量
6540
原文標(biāo)題:詳解全志V85x內(nèi)G2D模塊實(shí)現(xiàn)圖片格式步驟方法
文章出處:【微信號(hào):gh_79acfa3aa3e3,微信公眾號(hào):全志在線】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄

全志V85x內(nèi)G2D模塊實(shí)現(xiàn)圖片格式步驟方法
評(píng)論