| 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 相同的物理空间内,4K 的物理像素是 1080p 的 4 倍。
利益相关方
教员:neelsa@google.com
审核者:
- 输入:neelsa@google.com, quiche@google.com
- 无障碍功能:lucasradaelli@google.com
- Scenic:jaeheon@google.com、dworsham@google.com、jjosh@google.com
共同化:
此设计的详细版本已在内部与 Scenic、Input 和 Accessibility 团队进行了审核。我们还讨论了替代解决方案。
术语库
- 《平面国》
- Scenic 的全新 2D 合成 API。
- Gfx
- Scenic 中已弃用的旧 3D 合成 API。
- 查看
- 图形内容的视觉区域。
- 它具有坐标系、边界框,并通过视图树与其祖先建立明确的空间关系。
- HiDPI
- 每英寸的点数较高。
- 行业术语,用于指在相同物理区域内包含更多像素的显示屏。例如,屏幕密度为 240 dpi 或更高的屏幕被视为 HiDPI 屏幕。
- PP
- 物理像素。
- 显示屏的实际像素数。例如,如果同一款笔记本电脑有 4K 和 FHD 屏幕变体,4K 屏幕的实际像素数为 3840x2160,FHD 屏幕的实际像素数为 1920x1080,因此图标在两种笔记本电脑变体上的显示尺寸相同,只是在 HiDPI 显示屏上更清晰
- DIP
- 设备无关像素,也称为逻辑显示像素或密度无关像素。
- 显示屏的逻辑像素数。也就是说,如果同一款笔记本电脑有 4K 和 FHD 屏幕变体,则 4K 和 FHD 屏幕很可能都具有 1920x1080 的设备无关像素。
- DPR
- 设备像素比。
- 显示屏的物理像素与显示屏的设备无关像素之间的比率。
- LP
- 逻辑视图像素,也称为视图的设备无关像素
- 视图的逻辑像素数。影响内容布局。
- AP
- 分配像素。
- View 的绘制缓冲区分配像素数。
- PSS
- 家长设置的比例,也称为累积比例。
- 所有父级 SetScale() 值相乘。视图的 DIP 与显示屏的 DIP 之间的比率。
设计
为了适应“动机”部分中描述的所有使用情形,我们定义了一组关系,用于确定父视图可以为其子视图设置哪些值(父视图定义)、哪些值只能由 Flatland 设置(系统定义),以及子视图可以观测到哪些值(子视图观测)。
设备像素比由系统统一为单个显示屏上的所有视图定义。DPR 是由儿童观察到的。
子视图的大小以 LP 为单位。此大小由父级定义,并由子级观察。如果视图的 LP 大小和对齐方式与用于渲染视图的区域的显示屏 DIP 精确匹配,则该视图具有最佳分辨率。视图应表现得好像具有最佳分辨率,即在大小和对齐方面 LP=DIP。不过,最佳分辨率并非由子视图观测到,并且可以被父视图(使用缩放,见下文)有意打破,以实现放大或 GNOME 的活动概览等功能。
以浮点值的形式引入了缩放比例。它是父级定义的,但未被子级观察到!子视图的父级设置的缩放比例是该子视图的所有祖先视图引入的所有缩放比例的乘积。PSS 描述了子视图的 LP 与显示屏的 DIP 之间的比率。通过隐藏 PSS,Flatland 可以保留对子视图在显示屏上占据多少物理像素的控制权,而无需在进行上采样或下采样时强制子视图重新分配或重新呈现。
我们使用分配像素进一步区分,分配像素是指用于呈现要显示的内容的缓冲区的大小。这是一个客户端实现细节,但为了避免混淆,我们描述一下它与其他像素空间的关系:
- HiDPI 感知型客户端希望显示清晰,并且可以控制内容的大小。其分配像素是逻辑视图像素乘以 DPR。
- DPR 不敏感的客户端只想以一种尺寸呈现内容。它们会忽略 DPR,并且其分配像素等于其逻辑视图像素。
- 自定义分配客户拥有强制执行其分配像素的内容,即视频播放器或 WebCanvas。这些客户端将定义分配像素与逻辑视图像素之间的关系。
Flatland 映射:
- PP显示 = DIP显示* DPR
- PP视图 = LP视图 * PSS * DPR
- AP查看到 LP查看实际上是客户自己的业务。
- 建议为支持 HiDPI 的客户端设置 AP视图 = LP视图 * 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 会作为缩放比例应用于每个图片。如果客户端想要支持 HiDPI,则应使用给定的 LP 来布局其内容,但应使用报告的 DPR 来分配更大的缓冲区,以抵消 Scenic 的缩放效果。
PSS 不会向儿童传达。这意味着通过 Flatland 进行放大可能会导致模糊伪影。不过,这比强制客户端重新分配和重新呈现要好,例如,因为缓冲区大小会按缩放比例增大,从而导致出现内存不足 (OOM) 风险。
我们最终可能会得到具有浮点比例的非整数像素。如果我们以一致的方式附加到附近的整数像素值(舍入),就不会出现伪影。
Flatland 客户端可能需要从逻辑像素转换为物理像素,这不仅需要知道 DPR,还需要知道 PSS。不过,这仅适用于输入,因此此设计会将此转换信息推送到 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 的比例缩放,并应用了 2 的 DPR,则它们将获得 10 的 pixel_scale 并分配 10 倍大的缓冲区。此提案区分了 DPR 和 PSS,因此不必要的分配已消失。
此提案降低了客户端对重新分配和重新布局的预期。由于我们不再依赖 Flatland 客户端来响应缩放更改,因此可以实现更平滑的上采样和下采样操作。
安全注意事项
此提案不会影响 Flatland API 的安全模型。有关其他图形操作(例如限制视图的输入接收区域的剪辑)的 API 保证仍然适用于缩放后的内容。
此提案减少了传递给 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 文档,以说明 HiDPI 感知客户端行为以及缩放功能的工作方式。
缺点、替代方案和未知因素
实施此提案的成本并不高。此提案建议采用一种 DPR 解决方案,无论使用哪种显示硬件,该解决方案都能正常运行。它还可扩展用于多显示屏用例。
我们曾考虑过此设计的几种替代方案。
- 在某些 Chromium 配置中,DPR 已添加为可配置的静态值。 这显然无法在不同应用之间实现可伸缩性。
- 为避免舍入问题,我们曾考虑仅允许整数比例因子。 不过,在某些 DPR 配置中,此规则也有例外情况。
- 当有浮点值时,我们可能会进入缓慢的子像素渲染路径。不过,没有充分的理由这样做,而且不允许将性能传递缓冲区直接传递给显示屏会影响性能。
在先技术和参考资料
- RFC-0162:Flatland
- RFC-0147:视图系统
- RFC-0166:一个界面堆栈
- Flatland 在架构上与 Wayland 协议有一些相似之处,后者以类似于建议的设计的方式处理高密度表面。