国产精品久久久aaaa,日日干夜夜操天天插,亚洲乱熟女香蕉一区二区三区少妇,99精品国产高清一区二区三区,国产成人精品一区二区色戒,久久久国产精品成人免费,亚洲精品毛片久久久久,99久久婷婷国产综合精品电影,国产一区二区三区任你鲁

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

double buffer的fbdev驅(qū)動與應(yīng)用

FPGA之家 ? 來源:CSDN技術(shù)社區(qū) ? 作者:嵌入式Hacker ? 2021-03-21 11:26 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

一、為何需要 double buffer?

single buffer 會導(dǎo)致:

屏幕撕裂(tearing),即在屏幕上同時看到多幀數(shù)據(jù)拼接在一起。

點擊查看大圖

single buffer 為何會造成撕裂:

refresh rate 和 frame rate 不一致。

refresh rate 表示的是 屏幕每秒能更新多少次顯示,例如 30hz / 60hz。

點擊查看大圖

frame rate 表示的是 lcd controller / gpu 每秒能繪制多少幀數(shù)據(jù),例如 30fps / 60fps。

點擊查看大圖

LCD controller / gpu 和 屏幕協(xié)作完成一幀圖像的顯示:

點擊查看大圖

在 single buffer 的場景下,LCD user 和 LCD controller / gpu 總是在共用同一個 framebuffer,且沒有同步機(jī)制。

LCD user 是寫者,LCD controller / gpu 是讀者。

由于存在競爭關(guān)系且讀寫沒有同步機(jī)制,framebuffer 里必須會發(fā)生同時存在frame N 和 frame N-1 的數(shù)據(jù),此時 LCD 將 framebuffer 的數(shù)據(jù)顯示出來時,就會看到撕裂的效果:

點擊查看大圖

可以通過 double buffer+vsync 解決撕裂的問題。

double buffer,顧名思義,就是有 2 個 framebuffer,其工作邏輯如下:

LCD controller : draw fb0 to screen

LCD user : write data to fb1

LCD controller : draw fb1 to screen

LCD user : write data to fb0

循環(huán)。..

vsync 機(jī)制則用于確保一幀圖像能不被打斷地顯示在屏幕。

如何支持 double buffer?

需要驅(qū)動和應(yīng)用互相配合:

二、編寫支持 double buffer 的fbdev 驅(qū)動

fbdev 框圖:

先梳理一下思路:

讓驅(qū)動支持 double buffer 需要做 3 件事。

1. 申請2 x buffer:

size = (2 * width * height);

fbi-》screen_base = dma_alloc_wc(sfb-》dev, size, &map_dma, GFP_KERNEL);

2. 將 buffer 相關(guān)的信息保存 struct fb_info-》 struct fb_var_screeninfo。

struct fb_var_screeninfo {

__u32 xres; /* visible resolution */

__u32 yres;

__u32 xres_virtual; /* virtual resolution */

__u32 yres_virtual;

__u32 xoffset; /* offset from virtual to visible */

__u32 yoffset; /* resolution */

。..

}

點擊查看大圖

xres 和 yres 是真實的 LCD 分辨率的寬和長;

xres_virtual 和 yres_virtual 是顯存區(qū)域的寬和長;

xoffset 和 yoffset 用于指定當(dāng)前使用哪一個 Buffer 進(jìn)行繪制。使用 Buffer0 時 ,xoffset = 0,yoffset=0; 使用 Buffer1 時,xoffset = 0, yoffset = yres * 1;

3. 支持切換 buffer,具體的就是實現(xiàn) ioctl:FBIOPAN_DISPLAY。

pan 的本意是平移,可以想象成顯存上方有一個取景框,平移取景框可以看到不同的顯示內(nèi)容。

實例分析:goldfishfb.c

goldfishfb.c 是虛擬硬件 goldfish 的 fbdev 驅(qū)動,我們可以參考這個文件,學(xué)習(xí)如何實現(xiàn) double buffer。

1. 分配 2 x buffer:

int goldfish_fb_probe()

{

。..

framesize = width * height * 2 * 2;

fb-》fb.screen_base = (char __force __iomem *)dma_alloc_coherent(&pdev-》dev, framesize, &fbpaddr, GFP_KERNEL);

}

2. 設(shè)置 fb_var_screeninfo:

int goldfish_fb_probe()

{

。..

fb-》fb.var.xres = width;

fb-》fb.var.yres = height;

fb-》fb.var.xres_virtual = width;

fb-》fb.var.yres_virtual = height * 2;

}

3. 實現(xiàn) ioctl / FBIOPAN_DISPLAY:

static struct fb_ops goldfish_fb_ops = {

。..

.fb_pan_display = goldfish_fb_pan_display,

};

int goldfish_fb_pan_display()

{

。..

// 將新的顯存地址告知 lcd controller

writel(fb-》fb.fix.smem_start + fb-》fb.var.xres * 2 * var-》yoffset,

fb-》reg_base + FB_SET_BASE);

// 等待 LCD controller 的 vsync 信號

wait_event_timeout(fb-》wait,fb-》base_update_count != base_update_count, HZ / 15);

}

當(dāng)LCD controller 將一幀圖像完整地顯示在 LCD 上后,就會產(chǎn)生一個中斷,在中斷里就會執(zhí)行喚醒睡眠在 fb_pan_display 里的進(jìn)程。

如果你想多了解一些,可以閱讀 DRM 框架里的 fbdev 兼容代碼,此代碼也是支持 double buffer的:

linux/drivers/gpu/drm/*/*_drm_fbdev.c

linux/drivers/gpu/drm/drm_fb_helper.c

三、編寫支持 double buffer 的 fbdev 應(yīng)用

驅(qū)動支持 double buffer 后,還得在應(yīng)用程序里將其使用起來。

先梳理一下思路:

檢查是否支持 double buffer;

使能 double buffer:FBIOPUT_VSCREENINFO;

更新 buffer 里數(shù)據(jù);

通知驅(qū)動切換 buffer:FBIOPAN_DISPLAY;

等待切換完成:FBIO_WAITFORVSYNC;

實例分析:show_color.c

static int fd_fb;

static struct fb_fix_screeninfo fix; /* Current fix */

static struct fb_var_screeninfo var; /* Current var */

static int screen_size;

static unsigned char *fb_base;

static unsigned int line_width;

static unsigned int pixel_width;

int main(int argc, char **argv)

{

int i;

int ret;

int buffer_num;

int buf_idx = 1;

char *buf_next;

unsigned int colors[] = {0x00FF0000, 0x0000FF00, 0x000000FF, 0, 0x00FFFFFF}; /* 0x00RRGGBB */

struct timespec time;

。..

fd_fb = open(“/dev/fb0”, O_RDWR);

ioctl(fd_fb, FBIOGET_FSCREENINFO, &fix);

ioctl(fd_fb, FBIOGET_VSCREENINFO, &var);

line_width = var.xres * var.bits_per_pixel / 8;

pixel_width = var.bits_per_pixel / 8;

screen_size = var.xres * var.yres * var.bits_per_pixel / 8;

// 1. 獲得 buffer 個數(shù)

buffer_num = fix.smem_len / screen_size;

printf(“buffer_num = %d

”, buffer_num);

fb_base = (unsigned char *)mmap(NULL , fix.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);

if (fb_base == (unsigned char *)-1) {

printf(“can‘t mmap

”);

return -1;

}

if ((argv[1][0] == ’s‘) || (buffer_num == 1)) {

printf(“single buffer:

”);

while (1) {

for (i = 0; i 《 sizeof(colors)/sizeof(colors[0]); i++) {

lcd_draw_screen(fb_base, colors[i]);

nanosleep(&time, NULL);

}

}

} else {

printf(“double buffer:

”);

// 2. 使能多 buffer

var.yres_virtual = buffer_num * var.yres;

ioctl(fd_fb, FBIOPUT_VSCREENINFO, &var);

while (1) {

for (i = 0; i 《 sizeof(colors)/sizeof(colors[0]); i++) {

// 3. 更新 buffer 里的數(shù)據(jù)

buf_next = fb_base + buf_idx * screen_size;

lcd_draw_screen(buf_next, colors[i]);

// 4. 通知驅(qū)動切換 buffer

var.yoffset = buf_idx * var.yres;

ret = ioctl(fd_fb, FBIOPAN_DISPLAY, &var);

if (ret 《 0) {

perror(“ioctl() / FBIOPAN_DISPLAY”);

}

// 5. 等待幀同步完成

ret = 0;

ioctl(fd_fb, FBIO_WAITFORVSYNC, &ret);

if (ret 《 0) {

perror(“ioctl() / FBIO_WAITFORVSYNC”);

}

buf_idx = !buf_idx;

nanosleep(&time, NULL);

}

}

}

munmap(fb_base , screen_size);

close(fd_fb);

return 0;

}

運行:

$ 。/show_color single

buffer_num = 1

single buffer:

$ 。/show_color double

buffer_num = 2

double buffer:

該程序會在屏幕上循環(huán)的顯示不同的顏色。

當(dāng)傳入 “single” 參數(shù)時,使用單 buffer,可見撕裂。

當(dāng)傳入 “double” 參數(shù)時,使用雙 buffer,不再撕裂。

代碼不是很復(fù)雜,我就不再詳細(xì)分析了。

如果你想多了解一些,可以閱讀開源軟件 SDL-1.2 里的 sdl_fbvideo.c,此代碼也支持了 double buffer。
編輯:lyn

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 驅(qū)動
    +關(guān)注

    關(guān)注

    12

    文章

    1956

    瀏覽量

    88540
  • 編輯
    +關(guān)注

    關(guān)注

    0

    文章

    28

    瀏覽量

    11833

原文標(biāo)題:Linux 驅(qū)動開發(fā) / fbdev 雙緩存 / 快速入門

文章出處:【微信號:zhuyandz,微信公眾號:FPGA之家】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關(guān)推薦
    熱點推薦

    在GUI GUIDER中如何啟用eSingle Buffer

    這一問題,行業(yè)長期依賴雙緩沖(Ping-pong Buffer) 或 多緩沖(Multi Buffer),用更多顯存換來更穩(wěn)定的刷新體驗。
    的頭像 發(fā)表于 02-09 09:43 ?403次閱讀
    在GUI GUIDER中如何啟用eSingle <b class='flag-5'>Buffer</b>

    深入解析DS25MB100:2.5 Gbps 2:1/1:2 CML Mux/Buffer的卓越性能與應(yīng)用

    2.5 Gbps 2:1/1:2 CML Mux/Buffer,憑借其出色的信號調(diào)理能力和豐富的特性,在背板驅(qū)動、電纜驅(qū)動以及冗余和信號調(diào)理等應(yīng)用中展現(xiàn)出強大的優(yōu)勢。本文將深入剖析DS25MB100的特點
    的頭像 發(fā)表于 12-27 14:10 ?622次閱讀

    深度剖析DS42MB100:4.25 - Gbps 2:1/1:2 CML MUX/Buffer的卓越性能與應(yīng)用

    深度剖析DS42MB100:4.25 - Gbps 2:1/1:2 CML MUX/Buffer的卓越性能與應(yīng)用 在高速數(shù)據(jù)傳輸?shù)念I(lǐng)域中,信號的質(zhì)量和穩(wěn)定性是至關(guān)重要的。今天我們要詳細(xì)探討
    的頭像 發(fā)表于 12-27 10:45 ?737次閱讀

    STM32H7使用Serial V2框架配合DMA,可以修改DMA的buffer內(nèi)存位置嗎?

    因為主內(nèi)存設(shè)置在了dtcm,不能被dma訪問,然而serial v2框架開啟dma,緩存使用的是動態(tài)分配的內(nèi)存,要如何修改buffer位置呢
    發(fā)表于 10-09 07:04

    USB讀RAM buffer使用規(guī)范建議

    Questions:硬件和軟件同時去訪問 USB RAM buffer 造成數(shù)據(jù)亂掉或丟失 造成亂碼流程: 軟件設(shè)置 USB Valid 關(guān)總中斷,USB 收數(shù)據(jù)到 RAM Buffer,此時
    發(fā)表于 09-22 17:27

    【RA4M2-SENSOR】I2C驅(qū)動OLED

    使用 SCI 下的 I2C 來驅(qū)動 OLED 首先配置 SCI_I2C0 參數(shù)保持默認(rèn)就行 底層驅(qū)動 volatile int i2c_send_complete_flag = 0
    發(fā)表于 09-02 18:19

    SN74HCT244 Octal Buffer/Line Driver技術(shù)解析與應(yīng)用指南

    Texas Instruments SN74HCT244/SN74HCT244-Q1八路緩沖器和線路驅(qū)動器專門設(shè)計用于提高三態(tài)存儲器地址驅(qū)動器、時鐘驅(qū)動器以及總線導(dǎo)向接收器和發(fā)送器的性能和密度
    的頭像 發(fā)表于 08-29 11:27 ?1081次閱讀
    SN74HCT244 Octal <b class='flag-5'>Buffer</b>/Line Driver技術(shù)解析與應(yīng)用指南

    什么情況會導(dǎo)致BUFFER_RYD一直為低電平?

    ,在c++ streamer中檢測是否成接收到USB_BULK數(shù)據(jù),結(jié)果顯示4014可以接收到USB_BULK數(shù)據(jù),4024不能接收到USB_BULK數(shù)據(jù)。結(jié)果如下圖: 2、BUFFER_RDY信號
    發(fā)表于 08-14 06:21

    上海光機(jī)所在激光驅(qū)動離子加速方面取得新進(jìn)展

    ”和“On the study of proton acceleration from double-layer nanofoils”為題發(fā)表于Physics of Plasmas和AIP Advances。 激光驅(qū)動離子加速技術(shù)因超強超短激光技術(shù)的迅速進(jìn)展而受到廣泛關(guān)注
    的頭像 發(fā)表于 08-06 09:36 ?607次閱讀
    上海光機(jī)所在激光<b class='flag-5'>驅(qū)動</b>離子加速方面取得新進(jìn)展

    【創(chuàng)龍TL3562-MiniEVM開發(fā)板試用體驗】5、基于幀緩存區(qū)fd的LVGL

    , const lv_area_t * area, lv_color_t * color_p) void fbdev_get_sizes(uint32_t *width, uint32_t *height, uint32_t *dpi) 鼠標(biāo)的驅(qū)動位于lv_drivers
    發(fā)表于 07-31 15:17

    【RA-Eco-RA6M4開發(fā)板評測】串口收發(fā)測試與基于FIFO的串口驅(qū)動

    ){}uart_read_complete_flag = false;return ch; 接收可以在接收中斷打斷點看是否進(jìn)入中斷 二.基于FIFO的串口驅(qū)動上述接口應(yīng)用層不好使用,為了提供方便好用的應(yīng)用層串口讀寫接口,我們來封裝
    發(fā)表于 07-19 22:19

    socket緩沖區(qū)溢出的原因?怎么解決?

    ;, TARGET_RATE_KB_S); // 計算發(fā)送間隔 long delay_us = (long)((double)BUFFER_SIZE / (TARGET_RATE_KB_S * 1024
    發(fā)表于 06-19 06:34

    使用BulkInEpt-&gt;XferData(buffer, length)來傳輸數(shù)據(jù),將結(jié)果保存到文件,重復(fù)幾次后會得到奇怪的結(jié)果,為什么?

    我使用CYUSB3014-BZXC將數(shù)據(jù)從 FPGA 傳輸?shù)?PC。 我使用BulkInEpt->XferData(buffer, length)來傳輸數(shù)據(jù),length
    發(fā)表于 05-16 06:01

    國民技術(shù)N32G45x USB免驅(qū)動通訊例程

    USB 設(shè)備中有一大類就是 HID 設(shè)備,無需用戶自己開發(fā)驅(qū)動程序,對于一些數(shù)據(jù)量較少的場合(例如按鍵輸入、LED 顯示或一些小容量的芯片燒錄器等),使用用戶自定義 HID 設(shè)備是很合適
    發(fā)表于 04-17 10:02

    請問如何在Linux中使用幀緩沖區(qū)更新epdc顯示?

    /fbdev/mxc/mxc_epdc_v2_fb.c) 中的幀緩沖驅(qū)動程序 C 文件。我發(fā)現(xiàn) android (mxc_epdc_update_data) 中定義了一個函數(shù),用于從用戶空間更新數(shù)據(jù)。
    發(fā)表于 04-01 06:41