| RFC-0174:Flatland 中的缩放 | |
|---|---|
| 状态 | 已接受 |
| 区域 |
|
| 说明 | 定义如何在 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
审核人:
- 输入:neelsa@google.com、quiche@google.com
- 无障碍体验:lucasradaelli@google.com
- Scenic:jaeheon@google.com、dworsham@google.com、jjosh@google.com
共同化:
此设计的详细版本已在内部与 Scenic、Input 和 Accessibility 团队进行了审核。我们还讨论了替代解决方案。
术语库
- Flatland
- 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
- 分配像素。
- 视图的绘制缓冲区分配像素数。
- PSS
- 父级设置的缩放比例,也称为累积缩放比例。
- 所有父级 SetScale() 值相乘。视图的 DIP 与显示屏的 DIP 之间的比率。
设计
为了适应“设计初衷”部分中描述的所有用例,我们定义了一组关系,用于确定父视图可以对其子视图设置哪些值(父级定义)、哪些值只能由 Flatland 设置(系统定义),以及子视图可以观察哪些值(子视图观察)。
设备像素比 由系统为单个显示屏上的所有视图统一定义。DPR 由子视图观察。
子视图的大小以 LP 为单位进行测量。此大小由父级定义,并由子视图观察。如果视图的 LP 的大小和对齐方式与用于渲染视图的区域的显示屏 DIP 完全匹配,则视图具有 最佳分辨率 。视图应表现得好像具有最佳分辨率一样,即 LP 在大小和对齐方式上都等于 DIP。不过,最佳分辨率 不是 由子视图观察的,并且可以由父视图(使用 Scale,请参阅下文)有意破坏,以允许放大功能或 GNOME 的“活动概览”等功能。
Scale 以浮点值形式引入。它由父级定义,但不由子视图观察!子视图的父级设置的缩放比例是该子视图的所有祖先视图引入的所有缩放比例的乘积。PSS 描述了从子视图的 LP 到显示屏的 DIP 的比率。通过隐藏 PSS,Flatland 保留了对子视图在显示屏上占用的物理像素数量的控制权,而无需在进行上采样或降采样时强制子视图重新分配或重新呈现。
我们进一步区分了分配像素,即用于向显示屏呈现内容的缓冲区的大小。这是客户端实现细节,但为了避免混淆,我们描述了它与其他像素空间的关系:
- HiDPI 感知型客户端希望看起来清晰,并且可以控制其 内容的大小。其分配像素 是逻辑视图像素乘以 DPR。
- DPR 不感知型客户端希望仅以一种大小呈现内容。它们会忽略 DPR,并且其分配像素等于其逻辑视图像素。
- 自定义分配客户端具有强制其分配像素的内容,即视频播放器或 WebCanvas。这些客户端将定义其分配像素与逻辑视图像素之间的关系。
Flatland 映射:
- PPDisplay = DIPDisplay* DPR
- PPView = LPView * PSS * DPR
- APView 到 LPView 实际上是客户端自己的业务。
- 建议 HiDPI 感知型 客户端使用 APView = LPView * DPR。
上文所述的像素空间关系如图 1 所示。
图 1 - Flatland
建议的更改由以下 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 实例如何决定呈现其内容(是否缩放),并且无法对缩放比例更改做出反应。
隐私注意事项
此提案建议将 DPR 信息发送给 Flatland 客户端。设备像素比源自显示单元的物理和技术属性。虽然是非常具体的信息,但此属性和比率并非唯一,并且可能在多个硬件中通用,因此对于指纹识别并不是很有用。此外,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 协议有一些相似之处, 后者以 与建议的设计类似的方式 处理高密度表面。