| 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 中建立 Image 資源,以及即將推出的 2D API Flatland 的工作階段。
將緩衝區分配作業與 Scenic::Session 分開,可明確瞭解通訊協定的用途。 分配器只會處理緩衝區分配作業,而 Scenic::Sessions 則用於呈現和繪圖。
我們的 3D API 和即將推出的 2D API 都能使用分配器。因此可使用更複雜的圖像。
使用這個 API,更複雜的使用者可以在獨立的 Scenic::Sessions 之間共用 Image 資源。目前無法這麼做,因此通常需要重新分配。
設計
我們的建議主要是將緩衝區註冊和取消註冊功能從 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 - 圖片建立流程
請注意,現在已不需要取消緩衝區註冊。您可以在用戶端捨棄所有 BufferCollectionImportToken 執行個體,即可隱含地完成這項作業。考量到許多用戶端在意外關機時,無法執行取消註冊流程,這項做法可更有效地防範記憶體洩漏。
現有的緩衝區註冊功能需要用戶端定義專屬 ID,才能參照 BufferCollection。這會由 EVENTPAIR 取代,用戶端可輕鬆重複任意次數,以供參照。請參閱下方的現有流程。
protocol Session {
RegisterBufferCollection(uint32 buffer_id, fuchsia.sysmem.BufferCollectionToken token);
DeregisterBufferCollection(uint32 buffer_id);
};
建議設計的實作工作持續進行中,必要的重構也已完成。 如需實際變更,請參閱 fxr/498558 和 fxr/499479。
可用性
分配器 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,就只能顯示這張圖片,但無法修改或讀取。
缺點和替代方案
分配器 API 提案有兩個主要改善重點,其中任一項都可以取代現有的通訊協定和流程。
- 我們可以繼續使用專屬 ID 參照緩衝區集合,而不是事件配對。我們可以預期用戶端會選取專屬集合 ID,也可以從註冊呼叫傳回專屬集合 ID。
- 挑選專屬 ID 需要同步處理,包括用戶端尋找可用的 ID,以及等待 Allocator 確認後再使用。
- 惡意用戶端可能會輕易盜用專屬 ID。
- 我們需要明確的 DeregisterBufferCollection() 呼叫。
- 我們可以將 Allocator 保留在 Scenic::Session 和 Flatland 執行個體中,而不是公開新的通訊協定。
- 如果複雜的用戶端使用多個工作階段,仍會受到限制,無法使用註冊工作階段以外的緩衝區集合。