自 2025 年 3 月 27 日起,我們建議您使用 android-latest-release
而非 aosp-main
建構及貢獻 AOSP。詳情請參閱「Android 開放原始碼計畫變更」。
BufferQueue 和 Gralloc
透過集合功能整理內容
你可以依據偏好儲存及分類內容。
BufferQueue
類別會將產生圖形資料緩衝區的元件 (生產者) 連結至接受資料以供顯示或進一步處理的元件 (消費者)。幾乎所有透過系統移動圖形資料緩衝區的作業都會使用 BufferQueue
。
Gralloc 記憶體配置器會執行緩衝區配置作業,並透過兩個供應商專屬的 HIDL 介面 (請參閱 hardware/interfaces/graphics/allocator/
和 hardware/interfaces/graphics/mapper/
) 實作。allocate()
函式會接受預期的引數 (寬度、高度、像素格式) 以及一組用途標記。
BufferQueue 生產者和消費者
消費者會建立並擁有 BufferQueue
資料結構,且可與產生者位於不同的程序中。當生產端需要緩衝區時,會呼叫 dequeueBuffer()
來從 BufferQueue
要求空閒緩衝區,並指定緩衝區的寬度、高度、像素格式和用法標記。接著,生產者會填入緩衝區,並透過呼叫 queueBuffer()
將緩衝區傳回佇列。接著,取用端會使用 acquireBuffer()
取得緩衝區,並使用緩衝區內容。消費者完成後,會透過呼叫 releaseBuffer()
將緩衝區傳回至佇列。同步處理架構會控制緩衝區如何在 Android 圖形處理管道中移動。
BufferQueue
的部分特性 (例如可容納的緩衝區數量上限) 是由生產者和消費者共同決定。不過,BufferQueue
會視需要配置緩衝區。除非特性發生變更,否則緩衝區會保留在記憶體中;舉例來說,如果產生器要求不同大小的緩衝區,舊緩衝區會釋放,並視需要分配新的緩衝區。
BufferQueue
一律不會複製緩衝區內容,因為移動這麼多資料的效率不高。而是一律透過句柄傳遞緩衝區。
使用 Systrace 追蹤 BufferQueue
如要瞭解圖形緩衝區的移動方式,請使用
Systrace,這是用於記錄短時間內裝置活動的工具。系統層級的圖形程式碼和大部分的相關應用程式架構程式碼都已做好檢測。
如要使用 Systrace,請啟用 gfx
、view
和 sched
標記。追蹤記錄中會顯示 BufferQueue
物件。舉例來說,如果您在 Grafika 的 Play 影片 (SurfaceView) 執行期間進行追蹤,標示為 SurfaceView 的資料列會顯示在任何特定時間有多少緩衝區排入佇列。
在應用程式處於運作中時,這個值會遞增,進而觸發 MediaCodec 解碼器的轉譯作業。當 SurfaceFlinger 運作並使用緩衝區時,這個值會遞減。以 30 fps 顯示影片時,佇列的值會從 0 變為 1,因為約 60 fps 的顯示畫面可以跟上來源。SurfaceFlinger 只會在有工作要執行時喚醒,不會每秒喚醒 60 次。如果沒有任何內容更新螢幕,系統會嘗試避免工作並停用 VSync。
如果切換至 Grafika 的 Play 影片 (TextureView),並擷取新的追蹤記錄,您會看到標示為 com.android.grafika
 / com.android.grafika.PlayMovieActivity
的一列。這是主要 UI 層,也是另一個 BufferQueue
例項。由於 TextureView 會轉譯至 UI 圖層,而非獨立圖層,因此所有由影片驅動的更新都會顯示在此處。
Gralloc
Gralloc 配置器 HAL hardware/libhardware/include/hardware/gralloc.h
會透過用法旗標執行緩衝區配置作業。使用量旗標包括以下屬性:
- 從軟體 (CPU) 存取記憶體的頻率
- 硬體 (GPU) 存取記憶體的頻率
- 記憶體是否會用於 OpenGL ES (GLES) 紋理
- 記憶體是否會由影片編碼器使用
舉例來說,如果產生器的緩衝區格式指定 RGBA_8888
像素,且產生器指出緩衝區將從軟體存取 (意即應用程式會觸碰 CPU 上的像素),Gralloc 就會以 R-G-B-A 順序建立每個像素 4 個位元組的緩衝區。如果製作者指定其緩衝區只能透過硬體存取,並以 GLES 紋理形式存取,Gralloc 就能執行 GLES 驅動程式所需的任何操作,例如 BGRA 排序、非線性調色布局和其他色彩格式。允許硬體使用其偏好的格式,有助於提升效能。
部分值無法在特定平台上合併。舉例來說,影片編碼器旗標可能需要 YUV 像素,因此新增軟體存取權並指定 RGBA_8888
會失敗。
Gralloc 傳回的句柄可透過 Binder 在程序之間傳遞。
受保護的緩衝區
Gralloc 用途旗標 GRALLOC_USAGE_PROTECTED
可讓圖形緩衝區僅透過硬體保護路徑顯示。這些疊加平面是顯示 DRM 內容的唯一方式 (SurfaceFlinger 或 OpenGL ES 驅動程式無法存取受 DRM 保護的緩衝區)。
受 DRM 保護的影片只能在重疊平面上顯示。支援受保護內容的影片播放器必須使用 SurfaceView 實作。在未受保護的硬體上執行的軟體無法讀取或寫入緩衝區;硬體保護路徑必須顯示在硬體合成疊加層上 (也就是說,如果硬體合成器切換為 OpenGL ES 合成,受保護的影片就會從螢幕上消失)。
如要進一步瞭解受保護的內容,請參閱「DRM」。
這個頁面中的內容和程式碼範例均受《內容授權》中的授權所規範。Java 與 OpenJDK 是 Oracle 和/或其關係企業的商標或註冊商標。
上次更新時間:2025-07-27 (世界標準時間)。
[[["容易理解","easyToUnderstand","thumb-up"],["確實解決了我的問題","solvedMyProblem","thumb-up"],["其他","otherUp","thumb-up"]],[["缺少我需要的資訊","missingTheInformationINeed","thumb-down"],["過於複雜/步驟過多","tooComplicatedTooManySteps","thumb-down"],["過時","outOfDate","thumb-down"],["翻譯問題","translationIssue","thumb-down"],["示例/程式碼問題","samplesCodeIssue","thumb-down"],["其他","otherDown","thumb-down"]],["上次更新時間:2025-07-27 (世界標準時間)。"],[],[],null,["# BufferQueue and Gralloc\n\nThe `BufferQueue` class connects components that generate buffers of graphical\ndata (*producers* ) to components that accept the data for display or further\nprocessing (*consumers* ). Nearly everything that moves buffers of\ngraphical data through the system relies on `BufferQueue`.\n\nThe Gralloc memory allocator performs buffer allocations and is\nimplemented through two vendor-specific HIDL interfaces (see\n`hardware/interfaces/graphics/allocator/` and\n`hardware/interfaces/graphics/mapper/`). The\n`allocate()` function takes expected arguments (width, height, pixel\nformat) as well as a set of usage flags.\n\nBufferQueue producers and consumers\n-----------------------------------\n\nConsumers create and own the `BufferQueue` data structure and can exist in\ndifferent processes than their producers. When a producer needs a buffer, it\nrequests a free buffer from `BufferQueue` by calling\n`dequeueBuffer()`, specifying the buffers's width, height,\npixel format, and usage flags. The producer then populates the buffer and\nreturns the buffer to the queue by calling `queueBuffer()`. Next,\nthe consumer acquires the buffer with `acquireBuffer()` and makes\nuse of the buffer contents. When the consumer is done, it returns the buffer to\nthe queue by calling `releaseBuffer()`. The [sync framework](/docs/core/graphics/sync) controls\nhow buffers move through the Android graphics pipeline.\n\nSome characteristics of the `BufferQueue`, such as the maximum number of\nbuffers it can hold, are determined jointly by the producer and the consumer.\nHowever, `BufferQueue` allocates buffers as it needs them.\nBuffers are retained unless the characteristics change; for example, if a\nproducer requests buffers with a different size, old buffers are freed and new\nbuffers are allocated on demand.\n\nBuffer contents are never copied by `BufferQueue`, as moving that much data\naround is inefficient. Instead, buffers are always passed by a handle.\n\n### Track BufferQueue with Systrace\n\nTo understand how graphics buffers move around, use [Systrace](https://developer.android.com/studio/profile/systrace), a tool that records device activity over a short period of time.\nThe system-level graphics code is well instrumented, as is much of the relevant\napp framework code.\n\nTo use Systrace, enable the `gfx`, `view`, and\n`sched` tags. `BufferQueue` objects are displayed in the trace.\nAs an example, if you take a trace while\n[Grafika's Play\nvideo (SurfaceView)](https://github.com/google/grafika/blob/master/app/src/main/java/com/android/grafika/PlayMovieSurfaceActivity.java) is running, the row labeled *SurfaceView* tells you\nhow many buffers were queued up at any given time.\n\nThe value increments while the app is active, which triggers the rendering\nof frames by the MediaCodec decoder. The value decrements while SurfaceFlinger\nis working and consuming buffers. When showing video at 30 fps, the queue's value\nvaries from 0 to 1 because the \\~60 fps display can keep up with the source.\nSurfaceFlinger wakes only when there's work to be done, not 60 times per second.\nThe system tries to avoid work and disables VSync if nothing\nis updating the screen.\n\nIf you switch to [Grafika's Play video (TextureView)](https://github.com/google/grafika/blob/master/app/src/main/java/com/android/grafika/PlayMovieActivity.java) and grab a new trace,\nyou see a row labeled\n`com.android.grafika` / `com.android.grafika.PlayMovieActivity`.\nThis is the main UI layer, which is another `BufferQueue` instance. Because TextureView\nrenders into the UI layer rather than a separate layer, all of the\nvideo-driven updates are displayed here.\n\nGralloc\n-------\n\nThe Gralloc allocator HAL\n`hardware/libhardware/include/hardware/gralloc.h`\nperforms buffer allocations through usage flags. Usage flags include attributes\nsuch as:\n\n- How often the memory will be accessed from software (CPU)\n- How often the memory will be accessed from hardware (GPU)\n- Whether the memory will be used as an OpenGL ES (GLES) texture\n- Whether the memory will be used by a video encoder\n\nFor example, if a producer's buffer format specifies `RGBA_8888` pixels, and\nthe producer indicates that the buffer will be accessed from software (meaning an app\nwill touch pixels on the CPU), Gralloc creates a buffer with 4 bytes per pixel\nin R-G-B-A order. If instead, a producer specifies its buffer will be only\naccessed from hardware and as a GLES texture, Gralloc can do anything the GLES\ndriver wants, such as BGRA ordering, nonlinear swizzled layouts, and alternative\ncolor formats. Allowing the hardware to use its preferred format can\nimprove performance.\n\nSome values can't be combined on certain platforms. For example, the video\nencoder flag may require YUV pixels, so adding software access and specifying\n`RGBA_8888` fails.\n\nThe handle returned by Gralloc can be passed between processes\nthrough Binder.\n\n### Protected buffers\n\nThe Gralloc usage flag `GRALLOC_USAGE_PROTECTED` allows the\ngraphics buffer to be displayed only through a hardware-protected path. These\noverlay planes are the only way to display DRM content (DRM-protected buffers\ncan't be accessed by SurfaceFlinger or the OpenGL ES driver).\n\nDRM-protected video can be presented only on an overlay plane. Video players\nthat support protected content must be implemented with SurfaceView. Software\nrunning on unprotected hardware can't read or write the buffer;\nhardware-protected paths must appear on the Hardware Composer overlay (that is,\nprotected videos disappear from the display if Hardware Composer switches\nto OpenGL ES composition).\n\nFor details on protected content, see [DRM](/docs/core/media/drm)."]]