RFC-0161:風景式 Allocator API

RFC-0161:Scenic Allocator API
狀態已接受
區域
  • 圖形
說明

針對 Scenic Allocator 的舊版 API 設計文件,用於 API 校正。

Gerrit 變更
作者
審查人員
提交日期 (年-月-日)2021-03-19
審查日期 (年-月-日)2021-04-05

舊版 API 設計文件

這項 RFC 先前是以 API 設計文件提交,後來在 API 設計文件範本淘汰後轉換為 RFC。

摘要

本文件提出了提案,將 Scenic 的圖像資源分配提取到個別通訊協定中。

目標和用途

Allocator API 旨在改善現有的圖片分配流程,並使其與即將推出的變更相容。

  • 擴大從 Scenic::Session 配置的 BufferCollection 資源範圍。一個 BufferCollection 可用於在多個 Scenic::Session 和即將推出的 2D API Flatland 工作階段中建立 Image 資源。

  • 將緩衝區配置與 Scenic::Session 分開,可讓通訊協定的用途更加明確。Allocator 只會處理緩衝區配置,而 Scenic::Sessions 則用於呈現和繪製。

  • 分配器可供 3D API 和即將推出的 2D API 使用。這可讓您使用更複雜的圖形。

使用這個 API 後,更複雜的使用者可以在各自的獨立 Scenic::Session 之間共用圖片資源。但目前無法執行此操作,而且通常會強制重新配置。

設計

我們建議您將緩衝區註冊和註銷功能從 Scenic::Session 移至新通訊協定。請參閱下方的建議通訊協定。

library fuchsia.ui.composition;

/// A typed wrapper for an eventpair, representing the registry endpoint of a buffer collection.
resource struct BufferCollectionExportToken {
    zx.handle:EVENTPAIR value;
};

/// A typed wrapper for an eventpair, representing the Image import endpoint of a buffer
/// collection.
resource struct BufferCollectionImportToken {
    zx.handle:EVENTPAIR value;
};

protocol Allocator {
    /// A BufferCollection is a set of VMOs created by Sysmem and shared by a number of
    /// participants, one of which is the Flatland Renderer. Some content, such as Images, use a
    /// BufferCollection as their backing memory.
    ///
    /// Clients can send `export_token` to register buffer collections with Allocator to be used
    /// later in [`fuchsia.ui.composition/Flatland`] instances or other Scenic APIs. For
    /// example, by passing a [`BufferCollectionImportToken`] containing the matching peer of
    /// [`BufferCollectionExportToken`], they can create image resources via
    /// [`fuchsia.ui.composition/Flatland.CreateImage`]. Clients should wait for the response
    /// before using `import_token`.
    ///
    /// Flatland participates in the allocation of buffers by setting constraints on the
    /// BufferCollection referenced by `buffer_collection_token`. It will not block on buffers
    /// being allocated until the client creates content using the BufferCollection.
    ///
    /// The buffer collection registered with `export_token` is available and kept alive as long
    /// as the client holds a valid [`BufferCollectionImportToken`]. They will be garbage collected
    /// when all [`BufferCollectionImportToken`]s are closed and all the associated Image resources
    /// are released.
    RegisterBufferCollection(BufferCollectionExportToken export_token,
                             fuchsia.sysmem.BufferCollectionToken buffer_collection_token)
        -> () error RegisterBufferCollectionError;
};

圖 1 - 圖片建立流程 這張圖表呈現了關係用戶端、分配器和呈現 API。

請注意,您不再需要取消緩衝區註冊。您可以透過在用戶端端捨棄所有 BufferCollectionImportToken 例項,隱含執行這項操作。許多用戶端在發生意外關機時,無法順利執行註銷流程,因此這項功能可更有效地防範記憶體外洩。

現有的緩衝區註冊功能要求用戶端定義專屬 ID,以便參照 BufferCollection。這個事件已由 EVENTPAIR 取代,客戶可以輕鬆複製這個事件,並用於參照。請參閱下方的現有流程。

protocol Session {
    RegisterBufferCollection(uint32 buffer_id, fuchsia.sysmem.BufferCollectionToken token);

    DeregisterBufferCollection(uint32 buffer_id);
};

我們持續進行建議設計的開發工作,並完成必要的重構。如需瞭解實際變更,請參閱 fxr/498558 和 fxr/499479。

可用性

Allocator API 可讓您以不同的方式實現現有功能,從客戶的角度來看,這麼做會更簡單。

  • 用戶端會建立 EVENTPAIR,而非找出專屬 ID。
  • 用戶端可以放棄事件組的另一端,而非明確呼叫具有相同唯一 ID 的 DeregisterBufferCollection。
  • 用戶端可以在多個 Scenic::Session 中複製並使用事件對的另一端,以便建立 Image 資源。

請參閱下方 Scenic::Session 的使用模式示例。

fuchsia::ui::composition::AllocatorPtr scenic_allocator;
fuchsia::sysmem::BufferCollectionTokenSyncPtr token;
auto ref_pair = allocation::BufferCollectionImportExportTokens::New();
scenic::SessionPtr session;
scenic_allocator->RegisterBufferCollection(std::move(ref_pair.export_token), std::move(token),
                                             [&]() {
                                               session->Enqueue(scenic::NewCreateImage3Cmd(
                                                 image_id, width, height,
                                                 std::move(ref_pair.import_token), vmo_index));
                                             });

測試

我們計畫針對 API 新增大量單元測試。整合測試需要使用分配器,並與 Scenic::Session 協調,您可以透過轉換樹狀結構內的像素測試來執行這類測試。

效能考量

Allocator API 不會新增任何額外的 API 呼叫。這樣一來,用戶端就不會執行 DeregisterBufferCollection 呼叫。

安全性考量

Allocator API 會利用 EVENTPAIR 功能解決安全性問題。由於 EVENTPAIR 具有唯一性,且在建立時與其他端點有強烈關聯,因此惡意用戶端無法劫持並存取基礎緩衝區。如果他們以某種方式取得 EVENTPAIR,就只能顯示這張圖片,無法修改或讀取。

缺點和替代方案

Allocator API 提案有兩個主要改善要點,其中任一要點都可以由現有的通訊協定和流程取代。

  • 我們可以繼續使用專屬 ID 參照緩衝區集合,而非事件組合。我們可以預期用戶端會選取專屬的收集 ID,或是從註冊呼叫中傳回專屬的收集 ID。
    • 選擇專屬 ID 時需要進行同步處理,因為用戶端必須找到可運作的 ID,並等待分配器確認才能使用。
    • 惡意用戶端很容易劫持專屬 ID。
    • 我們需要明確的 DeregisterBufferCollection() 呼叫。
  • 我們可以將 Allocator 保留在 Scenic::Session 和 Flatland 例項中,而非公開新的通訊協定。
    • 使用多個工作階段的複雜用戶端仍有限制,無法使用註冊的一個工作階段以外的緩衝區集合。