RFC-0174:平面地图中的缩放 | |
---|---|
状态 | 已接受 |
区域 |
|
说明 | 定义如何在 Flatland 中处理图形放大操作。 |
问题 | |
Gerrit 更改 | |
作者 | |
审核人 | |
提交日期(年-月-日) | 2022-06-02 |
审核日期(年-月-日) | 2022-07-01 |
摘要
此 RFC 介绍了 Flatland 中如何处理图形缩放操作。Scenic 是 Fuchsia 的系统合成器,可以通过 Flatland 的 SetScale() 方法处理放大或缩小 Flatland 实例的输出。可以使用浮点缩放比例,并保证生成的图片避免了亚像素渲染。Flatland 实例仅知道设备像素比值。除了缩放设计之外,此 RFC 还定义了一些用于引用像素空间的常用术语。
设计初衷
作为完整的系统合成器,Flatland 应提供许多界面功能,而这些功能通常需要图形缩放操作。下面详细介绍了其中三种。
上采样
上采样是指增加 Flatland 实例或图片的渲染大小。 例如,请考虑放大功能。您可以通过请求 Scenic 对 Flatland 客户端应用的输出进行上采样来实现放大。
下采样
下采样是指缩减 Flatland 实例或图片的渲染大小。例如,请考虑 GNOME 的活动概览。图形系统 shell 可能希望让 Flatland 客户端应用继续以相同的分辨率进行渲染,但通过请求 Scenic 将其内容输出缩小到较小的矩形。
设备像素比
定义设备像素比是为了让显示屏制造商能够放大设备的分辨率,同时仍能在新屏幕上以相同大小显示针对较低分辨率设计的内容。例如,从远处看,4K 和 1080p 屏幕版本的笔记本电脑看起来完全一样,所有按钮和布局在实际尺寸上都相同。只有当您靠近屏幕时,才能看出 4K 画质更清晰,因为它在与 1080p 相同的物理空间内包含 4 倍的物理像素。
利益相关方
教练:neelsa@google.com
Reviewers:
- 输入:neelsa@google.com、quiche@google.com
- 无障碍功能:lucasradaelli@google.com
- 风景摄影:jaeheon@google.com、dworsham@google.com、jjosh@google.com
社交:
我们已在内部与 Scenic、输入和无障碍功能团队一起审核了此设计的详细版本。我们还讨论了其他解决方案。
术语库
- Flatland
- Scenic 的新 2D 合成 API。
- Gfx
- Scenic 的旧 3D 合成 API(已废弃)。
- 查看
- 图形内容的视觉区域。
- 它具有坐标系、边界框,并通过视图树与其祖先定义了空间关系。
- HiDPI
- 每英寸的点数较高。
- 用于表示在同一物理区域内填充更多像素的显示屏的行业术语。例如,屏幕密度为 240 dpi 或更高时,系统会将其视为高 DPI。
- PP
- 实体像素。
- 显示屏的物理像素数。例如,如果我们有相同笔记本电脑的 4K 和 FHD 屏幕变体,4K 的物理像素为 3840x2160,FHD 的物理像素为 1920x1080,因此图标在两个笔记本电脑变体上的显示大小相同,只是在 HiDPI 显示屏上更清晰
- DIP
- 设备无关像素(也称为逻辑显示像素或密度无关像素)。
- 显示屏的逻辑像素数。例如,如果同一台笔记本电脑有 4K 和 FHD 屏幕变体,那么 4K 和 FHD 屏幕最有可能具有 1920x1080 的设备独立像素。
- DPR
- 设备像素比。
- 显示屏的物理像素与显示屏的设备无关像素之间的比率。
- LP
- 逻辑 View 像素(也称为 View 的设备无关像素)
- 视图的逻辑像素数。会影响内容布局。
- AP
- 分配像素。
- 视图的绘制缓冲区分配像素数。
- PSS
- 父级设置的比例(也称为累积比例)。
- 所有父级 SetScale() 值都进行了乘法运算。视图的 DIP 与显示屏的 DIP 之间的比率。
设计
为了适应“动机”部分中所述的所有用例,我们定义了一组关系,用于确定父视图可以对其子视图设置哪些值(由父视图定义)、哪些值只能由 Flatland 设置(由系统定义),以及子视图可以观察哪些值(由子视图观察)。
设备像素比是系统为单个显示屏上的所有视图统一定义的。DPR 由儿童观察。
子视图的大小以 LP 为单位。此大小由父级定义并由子级观察。如果视图的 LP 的大小和对齐方式与用于渲染视图的区域的显示屏的 DIP 完全匹配,则视图具有最佳分辨率。视图应表现为具有最佳分辨率,其中 LP=DIP 在尺寸和对齐方面。不过,最佳分辨率不会被子视图观察到,并且可以被父视图(使用缩放,见下文)故意破坏,以允许放大或 GNOME 的活动概览等功能。
比例以浮点值的形式引入。它由父级定义,但不由子级观察!子视图的父级设置的缩放比例是该子视图的所有祖先视图引入的所有缩放比例的乘积。PSS 描述了子视图的 LP 与显示屏的 DIP 之间的比率。通过隐藏 PSS,Flatland 可以继续控制子视图在显示屏上占用的物理像素数量,而无需在上采样或下采样时强制子视图重新分配或重新呈现。
我们还进一步区分了分配像素,即用于呈现要显示的内容的缓冲区大小。这是客户端实现细节,但为了避免混淆,我们将介绍其与其他像素空间的关系:
- HiDPI 的客户端希望显示清晰的内容,并能够控制内容的大小。其分配像素是逻辑视图像素乘以 DPR。
- 不考虑 DPR 的客户希望以一种尺寸呈现内容。它们会忽略 DPR,并且其分配像素等于其逻辑视图像素。
- 自定义分配客户端的内容会强制执行其分配像素,例如视频播放器或 WebCanvas。这些客户端将在分配像素和逻辑视图像素之间定义自己的关系。
平面映射:
- PP显示 = DIP显示* DPR
- PPView = LPView * PSS * DPR
- APView 到 LPView 实际上是客户自己的业务。
- 对于支持高 DPI 的客户端,建议使用 APView = LPView * DPR。
上述像素空间关系如图 1 所示。
图 1 - 平面国
建议的更改由以下 FIDL 代码段表示:
type LayoutInfo = table {
/// The layout size of a View in logical pixels, defined by the parent's call to
/// [`SetViewportProperties`]. Clients should re-layout their content when this value changes.
1: logical_size fuchsia.math.SizeU;
/// The ratio from physical display pixels to the display's device independent pixels.
/// Clients should not necessarily re-layout their content when this value changes. Clients may
/// accommodate by reallocating their Image buffers that are adjusted by [`device_pixel_ratio`].
/// HiDPI-aware clients that want to avoid sampling artifacts should render onto a buffer with
/// at least the size round([`logical_size`] * [`device_pixel_ratio`]).
/// Note that rounding is not C-style float-to-int truncation. The floating-point product should
/// be converted to the nearest integer.
2: device_pixel_ratio fuchsia.math.VecF;
};
protocol Flatland {
/// Sets the scale on a Transform. The order of geometric attribute application is addressed
/// in the documentation for SetTranslation().
/// Note that if there is a Viewport set on this Transform, the child Flatland will not be notified
/// about the changes made here. This method should only be used if the intention is to upsample or
/// downsample the Viewport's output. Use [`SetViewportProperties`] if the intention is to resize or
/// relayout the Viewport.
SetScale(struct {
transform_id TransformId;
scale fuchsia.math.VecF;
});
}
在 Scenic 渲染或将图片发送到显示屏之前,系统会将 DPR 作为比例应用于每个图片。如果客户端想要支持高 DPI,则应使用给定的 LP 来布局其内容,但使用报告的 DPR 分配更大的缓冲区,以逆转 Scenic 的缩放效果。
不会向儿童传达 PSS。这意味着通过 Flatland 进行放大可能会导致模糊的伪影。不过,这比强制客户重新分配和重新呈现要好,例如,因为缓冲区大小会按缩放比例增大,并有 OOM 风险。
最终得到的像素可能是非整数,并且采用浮点比例。如果我们能够以一致的方式附加到附近的整数像素值(舍入),则不应出现伪影。
Flatland 客户端可能希望从逻辑像素转换为物理像素,这需要知道 PSS 和 DPR。不过,这仅适用于输入,因此此设计会将此转化信息推送到 fuchsia.ui.pointer
API。
客户端可以使用此 API 按照自己的节奏响应 DPR 更改。它们将同时收到有关这些更改的信号,因此不会出现级联延迟卡顿模式。
客户端应始终期望使用单个 DPR 值。未来,当我们支持多显示屏时,我们可以报告来自多个显示屏的单个 DPR 值,或显示屏的 DPR 值。
与旧版相比
请注意,在 Gfx(旧版 3D API)中,DPR 和 PSS 会相乘为一个值,并报告给子级。因此,缩放操作会导致客户端代码中的分配副作用,从而导致 OOM 和其他意外副作用,包括大规模架构权宜解决方法来实现放大等效果,以及 DPR 方面的混淆。这种 Flatland 设计有所不同,它建议子级仅需了解 DPR 以便处理图形。
Gfx 映射:
- PPView = LPView * pixel_scale
- pixel_scale = PSS * DPR
- pixel_scale 是 Gfx 返回的唯一指标。
实现
此设计涉及 fuchsia.ui.composition/Flatland
API 的更改。实现将分为三个主要步骤完成:
- 移除了树内和树外的
pixel_scale
字段(已废弃)的用法。 - 完成树内更改。根据显示屏报告的信息发送 DPR 信息。
- 更改了树内和树外客户端代码,以使用 DPR 信息来调整 AP。
性能
与 Gfx API 相比,此提案可减少感知 DPI 的客户端的内存用量。在 Gfx 中,DPR 和 PSS 会相乘为单个值,并报告给子级。感知 DPI 的客户端会响应所有缩放的累积。例如,如果它们由父项按 5 的比例缩放,并应用了 DPR 2,则它们会收到 pixel_scale
为 10 的值,并分配 10 倍大的缓冲区。此提案区分了 DPR 和 PSS,因此不再有不必要的分配。
此提案可降低客户对重新分配和重新布局的预期。由于我们不再依赖 Flatland 客户端来响应缩放更改,因此可以实现更流畅的上采样和下采样操作。
安全注意事项
此提案不会影响 Flatland API 的安全模型。该 API 保证其他图形操作(例如限制 View 的输入接收区域的剪裁)仍适用于放大的内容。
此提案会减少传递给 Flatland 视图的信息量。在 Gfx 中,DPR 和 PSS 会相乘为单个值,并报告给子项。此提案仅报告 DPR 信息。子 Flatland 实例无法指明其父 Flatland 实例如何决定呈现其内容(是否经过缩放),也无法对缩放更改做出响应。
隐私注意事项
此提案建议向 Flatland 客户发送 DPR 信息。设备像素比派生自显示单元的物理和技术属性。虽然这项属性和比率非常具体,但并不具有唯一性,并且可能在多种硬件中普遍存在,因此对创建设备指纹而言用处不大。此外,DPR 对准备高质量的图形输出至关重要。
测试
Flatland API 已采用分层方法进行测试,以下是测试的规模功能:
- Scenic 代码库中的单元测试。
- /src/ui/tests 中的界面集成测试,用于演练 Flatland API 周围的合约。
- 用于从 DPR 值不等于 1 的设备捕获输出像素的系统测试。
- Chromium 和 Flutter 等运行时会编写集成测试,以针对 SetScale() 的使用情况和不同的 DPR 值进行测试。
文档
在该 RFC 发布后,我们将更新一些 Flatland 文档,以介绍感知高 DPI 的客户端行为以及缩放的工作原理。
缺点、替代方案和未知情况
实现此方案的费用并不高。此提案建议了一个 DPR 解决方案,无论使用哪种显示硬件,该解决方案都能正常运行。它还可以扩展到多显示屏用例。
我们考虑了几种此设计的替代方案。
- 在某些 Chromium 配置中,DPR 已作为可配置的静态值添加。 显然,这种方法无法跨不同应用扩展。
- 为避免舍入问题,我们考虑仅允许整数缩放系数。不过,在某些 DPR 配置中,也有例外情况。
- 如果使用浮点值,我们可能会陷入缓慢的亚像素渲染路径。不过,没有强有力的理由这样做,因为这会导致性能无法直接将缓冲区传递给显示屏,从而影响性能。
在先技术和参考文档
- RFC-0162:Flatland
- RFC-0147:View 系统
- RFC-0166:一个界面堆栈
- Flatland 与 Wayland 协议在架构方面有一些相似之处,Wayland 协议处理高密度 Surface 的方式与所提议的设计类似。