在嵌入式平台Linux,主要通過framebuffer來顯示UI。FrameBuffer實際上就是嵌入式系統中專門為GPU所保留的一塊連續的物理內存,LED通過專門的總線從framebuffer讀取數據,顯示到屏幕上。
根據系統中framebuffer的數量,可以分成單buffer和雙buffer兩種。
先來說說單buffer:
CPU往framebuffer上寫,LED從framebuffer讀,這是兩個同時進行的過程,需要在時間上配合,否則會出現問題。
如果CPU往framebuffer上寫的速度>LED從framebuffer讀的速度,那麼就有可能出現LED在一行一行的讀取前一屏數據的時候,CPU卻已經刷新了整屏,從而導致顯示混亂。這裡要注意,LED從framebuffer讀的速度並不等於屏幕的刷新頻率,如果刷新頻率為60hz,那麼很有可能LED花了3個ms去讀,剩余的時間都在等待。應該說CPU往framebuffer寫的速度>LED從framebuffer讀的速度還是很困難的。
如果CPU往framebuffer寫的速度太慢,也會出現屏幕閃爍的問題。比如說要畫一幅圖,CPU首先將其填充為白色,這時LED刷新,屏幕顯示為白色,之後開始畫完其他內容,屏幕正常顯示。這時給用戶的感覺就是屏幕一閃。這就要求CPU盡快的畫完一屏,盡量保證寫一屏不要跨越LED刷新周期。
因此,在單framebuffer的時代,為了防止屏幕出現閃爍,我們一般是在內存中開辟一塊與framebuffer同樣大小的內容,將屏幕的內容都寫好,然後再執行一次內存拷貝。從而使寫framebuffer的時間盡可能的短。
但這種機制有問題,我以屏幕分辯率為320*240為例。
一塊framebuffer的大小為:320*240*4=0.3072M。
也就是說,我要先在內存中填寫0.3M的內存,然後再把這塊內存拷貝到framebuffer中。為了簡單起見,這裡我舉一個將屏幕置為白色的例子,排除屏幕內容計算的影響。
顯示的實際過程為,將內存中0.3M置為0,然後讀取這0.3M的內存,拷貝到Framebuffer中。
在我使用的嵌入式平台中,采用的是SDRAM,532Mhz的ARM11芯片。通過使用lmbench得到內存訪問的速率為:
*Local* Communication bandwidths in MB/s - bigger is better
-----------------------------------------------------------
Host OS Pipe AF TCP File Mmap Bcopy Bcopy Mem Mem
UNIX reread reread (libc) (hand) read
write
--------- ------------- ---- ---- ---- ------ ------ -------- ---- -----
phone Linux 2.6 79.1 94.7 13.3 47.1 135.9 78.6 77.8 135. 205.9
很奇怪,為什麼讀會比寫慢,可能與cache有關,這裡先不用去管它。