幀緩衝裝置

上次修訂時間:2001 年 5 月 10 日

0. 介紹

幀緩衝裝置為圖形硬體提供了一個抽象。它代表了某些影片硬體的幀緩衝,並允許應用程式軟體透過定義良好的介面訪問圖形硬體,因此軟體不需要了解任何關於底層(硬體暫存器)的東西。

該裝置透過特殊的裝置節點訪問,通常位於 /dev 目錄中,例如 /dev/fb*。

1. /dev/fb* 的使用者視角

從使用者的角度來看,幀緩衝裝置看起來就像 /dev 中的任何其他裝置。它是一個主裝置號為 29 的字元裝置;次裝置號指定幀緩衝編號。

按照慣例,使用以下裝置節點(數字表示裝置次裝置號)

 0 = /dev/fb0      First frame buffer
 1 = /dev/fb1      Second frame buffer
     ...
31 = /dev/fb31     32nd frame buffer

為了向後相容,您可能需要建立以下符號連結

/dev/fb0current -> fb0
/dev/fb1current -> fb1

等等...

幀緩衝裝置也是普通記憶體裝置,這意味著您可以讀取和寫入它們的內容。 例如,您可以透過以下方式製作螢幕快照

cp /dev/fb0 myfile

也可以同時存在多個幀緩衝,例如,如果除了內建硬體之外,您還有一張顯示卡。 相應的幀緩衝裝置(/dev/fb0 和 /dev/fb1 等)獨立工作。

使用幀緩衝裝置的應用程式軟體(例如 X 伺服器)預設將使用 /dev/fb0(較舊的軟體使用 /dev/fb0current)。 您可以透過將環境變數 $FRAMEBUFFER 設定為幀緩衝裝置的路徑名來指定替代幀緩衝裝置,例如(對於 sh/bash 使用者)

export FRAMEBUFFER=/dev/fb1

或(對於 csh 使用者)

setenv FRAMEBUFFER /dev/fb1

此後,X 伺服器將使用第二個幀緩衝。

2. /dev/fb* 的程式設計師視角

如您所知,幀緩衝裝置是像 /dev/mem 這樣的記憶體裝置,它具有相同的功能。 您可以讀取它、寫入它、定址到其中的某個位置並對其進行 mmap()(主要用法)。 區別僅在於特殊檔案中出現的記憶體不是整個記憶體,而是某些影片硬體的幀緩衝。

/dev/fb* 還允許對其進行多個 ioctl 操作,透過這些操作可以查詢和設定有關硬體的許多資訊。 顏色對映處理也透過 ioctl 進行。 檢視 <linux/fb.h> 以獲取有關存在的 ioctl 以及它們所作用的資料結構的更多資訊。 這是一個簡要概述

  • 您可以請求有關硬體的不可更改的資訊,例如名稱、螢幕記憶體的組織方式(平面、壓縮畫素...)以及螢幕記憶體的地址和長度。

  • 您可以請求和更改有關硬體的可變資訊,例如可見和虛擬幾何體、深度、顏色對映格式、時序等。 如果您嘗試更改該資訊,驅動程式可能會舍入一些值以滿足硬體的功能(如果不可能,則返回 EINVAL)。

  • 您可以獲取和設定顏色對映的一部分。 通訊使用每個顏色部分(紅色、綠色、藍色、透明度)16 位來完成,以支援所有現有硬體。 驅動程式會完成所有需要的計算,以將其應用於硬體(向下舍入到更少的位,可能會丟棄透明度)。

所有這些硬體抽象使得應用程式的實現更加容易和更具可移植性。 例如,X 伺服器完全在 /dev/fb* 上執行,因此不需要知道例如具體硬體的顏色暫存器是如何組織的。 XF68_FBDev 是用於點陣圖、非加速影片硬體的通用 X 伺服器。 必須構建到應用程式中的唯一東西是螢幕組織(位平面或塊狀畫素等),因為它直接在幀緩衝影像資料上執行。

將來計劃將圖形卡等幀緩衝驅動程式實現為執行時載入的核心模組。 這樣的驅動程式只需呼叫 register_framebuffer() 並提供一些函式。 獨立於核心編寫和分發此類驅動程式將節省很多麻煩...

3. 幀緩衝解析度維護

幀緩衝解析度使用實用程式 fbset 維護。 它可以更改幀緩衝裝置的影片模式屬性。 它的主要用途是更改當前的影片模式,例如在您的 /etc/rc.*/etc/init.d/* 檔案之一中啟動期間。

Fbset 使用儲存在配置檔案中的影片模式資料庫,因此您可以輕鬆新增自己的模式並使用簡單的識別符號引用它們。

4. X 伺服器

X 伺服器 (XF68_FBDev) 是幀緩衝裝置最著名的應用程式。 從 XFree86 release 3.2 開始,X 伺服器是 XFree86 的一部分,並具有 2 種模式

  • 如果 /etc/XF86Config 檔案中 fbdev 驅動程式的 Display 小節包含

    Modes "default"
    

    行,X 伺服器將使用上述方案,即它將在 /dev/fb0(如果設定了 $FRAMEBUFFER)確定的解析度下啟動。 您仍然必須指定顏色深度(使用 Depth 關鍵字)和虛擬解析度(使用 Virtual 關鍵字)。 這是 XFree86 提供的配置檔案的預設設定。 它是最簡單的配置,但有一些限制。

  • 因此,也可以在 /etc/XF86Config 檔案中指定解析度。 這允許在保持相同虛擬桌面大小的同時進行動態解析度切換。 使用的幀緩衝裝置仍然是 /dev/fb0current(或 $FRAMEBUFFER),但可用解析度現在由 /etc/XF86Config 定義。 缺點是您必須以不同的格式指定時序(但 fbset -x 可能會有所幫助)。

要調整影片模式,您可以使用 fbset 或 xvidtune。 請注意,xvidtune 與 XF68_FBDev 不能 100% 相容:報告的時鐘值始終不正確。

5. 影片模式時序

監視器透過使用電子束在螢幕上繪製圖像(彩色型號使用 3 個電子束,單色監視器使用 1 個電子束)。 螢幕正面覆蓋著彩色熒光粉(畫素)的圖案。 如果熒光粉被電子擊中,它會發射光子,從而變得可見。

電子束從左到右,從螢幕頂部到底部繪製水平線(掃描線)。 透過修改電子束的強度,可以顯示具有各種顏色和強度的畫素。

在每條掃描線之後,電子束必須移回螢幕的左側並移動到下一行:這稱為水平回掃。 在繪製完整個螢幕(幀)後,光束移回左上角:這稱為垂直回掃。 在水平和垂直回掃期間,電子束關閉(消隱)。

電子束繪製畫素的速度由圖形板中的點時鐘決定。 對於例如 28.37516 MHz(每秒數百萬個週期)的點時鐘,每個畫素的長度為 35242 ps(皮秒)

1/(28.37516E6 Hz) = 35.242E-9 s

如果螢幕解析度為 640x480,則需要

640*35.242E-9 s = 22.555E-6 s

才能在一條掃描線上繪製 640 (xres) 個畫素。 但水平回掃也需要時間(例如 272 畫素),因此完整的掃描線需要

(640+272)*35.242E-9 s = 32.141E-6 s

我們會說水平掃描速率約為 31 kHz

1/(32.141E-6 s) = 31.113E3 Hz

完整的螢幕計算 480 (yres) 行,但我們也必須考慮垂直回掃(例如 49 )。 因此,完整的螢幕將需要

(480+49)*32.141E-6 s = 17.002E-3 s

垂直掃描速率約為 59 Hz

1/(17.002E-3 s) = 58.815 Hz

這意味著螢幕資料每秒重新整理約 59 次。 為了獲得沒有可見閃爍的穩定影像,VESA 建議垂直掃描速率至少為 72 Hz。 但感知到的閃爍非常依賴於人:有些人可以毫無問題地使用 50 Hz,而如果低於 80 Hz 我會注意到。

由於監視器不知道何時開始新的掃描線,因此圖形板將為每條掃描線提供同步脈衝(水平同步或 hsync)。 同樣,它為每個新幀提供同步脈衝(垂直同步或 vsync)。 影像在螢幕上的位置受到同步脈衝發生的時刻的影響。

下圖總結了所有時序。 水平回掃時間是左邊距、右邊距和 hsync 長度的總和,而垂直回掃時間是上邊距、下邊距和 vsync 長度的總和

+----------+---------------------------------------------+----------+-------+
|          |                ↑                            |          |       |
|          |                |upper_margin                |          |       |
|          |                ↓                            |          |       |
+----------###############################################----------+-------+
|          #                ↑                            #          |       |
|          #                |                            #          |       |
|          #                |                            #          |       |
|          #                |                            #          |       |
|   left   #                |                            #  right   | hsync |
|  margin  #                |       xres                 #  margin  |  len  |
|<-------->#<---------------+--------------------------->#<-------->|<----->|
|          #                |                            #          |       |
|          #                |                            #          |       |
|          #                |                            #          |       |
|          #                |yres                        #          |       |
|          #                |                            #          |       |
|          #                |                            #          |       |
|          #                |                            #          |       |
|          #                |                            #          |       |
|          #                |                            #          |       |
|          #                |                            #          |       |
|          #                |                            #          |       |
|          #                |                            #          |       |
|          #                ↓                            #          |       |
+----------###############################################----------+-------+
|          |                ↑                            |          |       |
|          |                |lower_margin                |          |       |
|          |                ↓                            |          |       |
+----------+---------------------------------------------+----------+-------+
|          |                ↑                            |          |       |
|          |                |vsync_len                   |          |       |
|          |                ↓                            |          |       |
+----------+---------------------------------------------+----------+-------+

幀緩衝裝置期望所有水平時序都以點時鐘數(以皮秒為單位,1E-12 秒)表示,而垂直時序以掃描線數表示。

6. 將 XFree86 時序值轉換為幀緩衝裝置時序

XFree86 模式行由以下欄位組成

"800x600"     50      800  856  976 1040    600  637  643  666
< name >     DCF       HR  SH1  SH2  HFL     VR  SV1  SV2  VFL

幀緩衝裝置使用以下欄位

  • pixclock:畫素時鐘,單位為 ps(皮秒)

  • left_margin:從同步到圖片的間隔

  • right_margin:從圖片到同步的間隔

  • upper_margin:從同步到圖片的間隔

  • lower_margin:從圖片到同步的間隔

  • hsync_len:水平同步的長度

  • vsync_len:垂直同步的長度

  1. 畫素時鐘

    xfree:單位為 MHz

    fb:單位為皮秒 (ps)

    pixclock = 1000000 / DCF

  2. 水平時序

    left_margin = HFL - SH2

    right_margin = SH1 - HR

    hsync_len = SH2 - SH1

  3. 垂直時序

    upper_margin = VFL - SV2

    lower_margin = SV1 - VR

    vsync_len = SV2 - SV1

可以在 XFree86 原始碼樹的“xc/programs/Xserver/hw/xfree86/doc/modeDB.txt”下找到 VESA 時序的良好示例。

7. 參考

有關幀緩衝裝置及其應用的更多具體資訊,請訪問 Linux-fbdev 網站

以及以下文件

  • fbset 的手冊頁:fbset(8), fb.modes(5)

  • XFree86 的手冊頁:XF68_FBDev(1), XF86Config(4/5)

  • 強大的核心原始碼

    • linux/drivers/video/

    • linux/include/linux/fb.h

    • linux/include/video/

8. 郵件列表

kernel.org 上有一個與幀緩衝裝置相關的郵件列表:linux-fbdev@vger.kernel.org

將您的 Web 瀏覽器指向 http://sourceforge.net/projects/linux-fbdev/ 以獲取訂閱資訊和存檔瀏覽。

9. 下載

所有必要的檔案都可以在

及其映象上找到。

fbset 的最新版本可以在

找到。

10. 鳴謝

本自述檔案由 Geert Uytterhoeven 編寫,部分基於 Roman Hodek 和 Martin Schaller 的原始 X-framebuffer.README。 第 6 節由 Frank Neumann 提供。