色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

double buffer的fbdev驅動與應用

FPGA之家 ? 來源:CSDN技術社區 ? 作者:嵌入式Hacker ? 2021-03-21 11:26 ? 次閱讀

一、為何需要 double buffer?

single buffer 會導致:

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

點擊查看大圖

single buffer 為何會造成撕裂:

refresh rate 和 frame rate 不一致。

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

點擊查看大圖

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

點擊查看大圖

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

點擊查看大圖

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

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

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

點擊查看大圖

可以通過 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

循環。..

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

如何支持 double buffer?

需要驅動和應用互相配合:

二、編寫支持 double buffer 的fbdev 驅動

fbdev 框圖:

先梳理一下思路:

讓驅動支持 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 相關的信息保存 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 是顯存區域的寬和長;

xoffset 和 yoffset 用于指定當前使用哪一個 Buffer 進行繪制。使用 Buffer0 時 ,xoffset = 0,yoffset=0; 使用 Buffer1 時,xoffset = 0, yoffset = yres * 1;

3. 支持切換 buffer,具體的就是實現 ioctl:FBIOPAN_DISPLAY。

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

實例分析:goldfishfb.c

goldfishfb.c 是虛擬硬件 goldfish 的 fbdev 驅動,我們可以參考這個文件,學習如何實現 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. 設置 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. 實現 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);

}

當LCD controller 將一幀圖像完整地顯示在 LCD 上后,就會產生一個中斷,在中斷里就會執行喚醒睡眠在 fb_pan_display 里的進程。

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

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

linux/drivers/gpu/drm/drm_fb_helper.c

三、編寫支持 double buffer 的 fbdev 應用

驅動支持 double buffer 后,還得在應用程序里將其使用起來。

先梳理一下思路:

檢查是否支持 double buffer;

使能 double buffer:FBIOPUT_VSCREENINFO;

更新 buffer 里數據;

通知驅動切換 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 個數

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 里的數據

buf_next = fb_base + buf_idx * screen_size;

lcd_draw_screen(buf_next, colors[i]);

// 4. 通知驅動切換 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:

該程序會在屏幕上循環的顯示不同的顏色。

當傳入 “single” 參數時,使用單 buffer,可見撕裂。

當傳入 “double” 參數時,使用雙 buffer,不再撕裂。

代碼不是很復雜,我就不再詳細分析了。

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

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 驅動
    +關注

    關注

    12

    文章

    1841

    瀏覽量

    85326
  • 編輯
    +關注

    關注

    0

    文章

    28

    瀏覽量

    11558

原文標題:Linux 驅動開發 / fbdev 雙緩存 / 快速入門

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

收藏 人收藏

    評論

    相關推薦

    Linux,IIO驅動完結有感

    01.3_DHT11驅動程序體驗_IMX6ULL01.3_DHT11驅動程序體驗_STM32MP15701.4_DHT11驅動程序分析01.5_通道的sysfs信息修改與體驗02.1_iio_
    的頭像 發表于 12-06 09:45 ?207次閱讀
    Linux,IIO<b class='flag-5'>驅動</b>完結有感

    江蘇潤石推出高驅動能力運算放大器RS8471

    Vcom是TFT-LCD液晶屏驅動用的信號,在屏內連接至每一個顯示單位,屏的尺寸越大,Vcom的走線越長,而驅動信號要求快速建立,否則顯示畫面就會產生鬼影、重影等異常現象,通用的設計方案都是采用所謂“Vcom Buffer”的高
    的頭像 發表于 11-29 09:28 ?266次閱讀
    江蘇潤石推出高<b class='flag-5'>驅動</b>能力運算放大器RS8471

    SN74HC14D buffer的數據速率是多大?

    該型號buffer的數據速率是多大?
    發表于 11-29 07:10

    CDCM61004時鐘Buffer是否支持SSC功能?

    CDCM61004 時鐘Buffer是否支持SSC功能
    發表于 11-08 16:09

    MSPM0 UART通信中DMA和Ring Buffer環形緩沖的應用

    電子發燒友網站提供《MSPM0 UART通信中DMA和Ring Buffer環形緩沖的應用.pdf》資料免費下載
    發表于 09-05 11:01 ?0次下載
    MSPM0 UART通信中DMA和Ring <b class='flag-5'>Buffer</b>環形緩沖的應用

    使用DRV401時如何提高驅動力?

    在使用DRV401時,在datasheet的EXTERNAL COMPENSATION COIL DRIVER中介紹可以通過增加buffer可提高驅動能力,但沒有將具體如何實現做詳細介紹,可否提供推薦的應用電路和buffer
    發表于 08-16 08:20

    esp-iot-solution攝像頭一直報溢出是怎么回事?

    ) //Double buffer #define DEMO_FRAME_INDEX DESCRIPTOR_FRAME_320_240_INDEX #define
    發表于 06-27 06:02

    STM32的DAC輸出有個BUFFER功能,BUFFer驅動能力究竟有多大,普通的運放輸出可以嗎?驅動LED可以嗎?

    DAC是輸出模擬電壓給外界參考,STM32的DAC輸出有個BUFFER功能,但不知這個BUFFer驅動能力究竟有多大,普通的運放輸出可以嗎?驅動LED可以嗎?有沒有人做過這塊,給個建
    發表于 05-15 07:42

    OpenHarmony語言基礎類庫【@ohos.buffer (Buffer)】

    Buffer對象用于表示固定長度的字節序列,是專門存放二進制數據的緩存區。
    的頭像 發表于 04-23 17:34 ?887次閱讀
    OpenHarmony語言基礎類庫【@ohos.<b class='flag-5'>buffer</b> (<b class='flag-5'>Buffer</b>)】

    PsoC62 EZI2C Buffer1緩存最大僅是多少?

    void EZI2C_1_Isr(void) { Cy_SCB_EZI2C_Interrupt(EZI2C_1_HW,EZI2C_1_context); } #define BUFFER
    發表于 02-02 06:18

    請問基于驅動器模式=High-Z、Input buffer=禁用設置的GPIO連接是什么?

    我正在使用 TRAVEO CYT2B9,我在 Architecture TRM 中看到了 GPIO 單元架構。 我想知道 Drive mode=High-Z、Input buffer=禁用
    發表于 01-26 06:26

    請問MINI54 SPI BUFFER怎么用?

    各位前輩,我想請問一下,MINI 54 SPI BUFFER 怎么使用?比如怎么定義,怎么引用。哪位可以告訴我一下,不勝感激。
    發表于 01-17 08:08

    時鐘Buffer芯片是什么?其作用是啥?它被用在什么地方?

    時鐘Buffer芯片是什么?其作用是啥?它被用在什么地方? 時鐘Buffer芯片是一種用于管理和增強電子設備中的時鐘信號的集成電路。時鐘信號在數字電子設備中非常重要,它用于同步各個模塊的工作,確保
    的頭像 發表于 01-16 15:10 ?4534次閱讀

    想實現unsigned char和double的轉換,為什么DSP仿真一直不對?

    請教數據類型轉換問題,處理器類型:ADSP21479,編譯器visual DSP 5.0。 想實現unsigned char和double的轉換(因為從外部接口接收到的是unsigned char
    發表于 01-11 08:29

    stm32f407 double類型

    篇文章中,我們討論一下STM32F407的雙精度浮點數(Double)類型。 首先,讓我們先了解什么是雙精度浮點數。雙精度浮點數是一種浮點數表示形式,它使用雙精度浮點數格式來表示實數。在STM32F407中,雙精度浮點數類型被定義為64位。這意味著它可以表示更大范圍的數值,并且具有更高的精確度,相
    的頭像 發表于 01-07 16:45 ?3056次閱讀
    主站蜘蛛池模板: 日日啪无需播放器| 99久久国产综合精品网成人影院| 办公室里做好紧好爽H| 欧美激情一区二区三区视频| 扒开美女的内衣亲吻漫画| 四房播播最新地址| 换脸国产AV一区二区三区| 18亚洲男同gay1069| 伊人久久精品中文字幕| 久久亚洲精品AV成人无码| freehd另类xxxx喷水| 天天看高清影视在线18| 好爽好深太大了再快一点| 51精品国产AV无码久久久| 日本久久久| 京香在线播放| YELLOW视频在线观看大全| 亚洲国产精品特色大片观看| 邻家美姨在线观看全集免费| 鬼灭之刃花街篇免费樱花动漫 | 99久久精品免费看国产一区二区| 翘臀后进美女白嫩屁股视频| 国产在线精品视频资源| 99国内精品久久久久久久清纯| 少爷不要别揉了高H| 久久99精品国产99久久6男男| bl撅高扒开臀缝哦| 亚洲欧美日韩另类精品一区二区三区| 麻花豆传媒剧国产免费mv观看| 国产成人精品免费视频软件| 2224x最新网站| 亚洲 成人网| 青青草在线 视频| 久久这里只有精品无码3D| 国产精品久久婷婷五月色| 99这里有精品视频视频| 一本到道免费线观看| 十分钟免费看完整视频| 男人网站在线| 久久九九免费| 好色女博士|