如何制作个人网站主页,小程序制作方法,深圳开发app公司,网站备案接入商是什么脏矩阵设计说明
背景介绍
一般情况下#xff0c;当屏幕内容绘制完毕后#xff0c;实际应用通常需要更新屏幕中的一部分内容#xff0c;而不是单纯显示一个静态图片在那。
如下图所示#xff0c;屏幕中有一个图片控件#xff08;Img2#xff09;和一个文本控件#xf…脏矩阵设计说明
背景介绍
一般情况下当屏幕内容绘制完毕后实际应用通常需要更新屏幕中的一部分内容而不是单纯显示一个静态图片在那。
如下图所示屏幕中有一个图片控件Img2和一个文本控件Change Text图片控件是静态不变的但是文本控件内容是需要变化的。从左边变到右边文本从《Change Text》变成《New Text》但是背景并没有变化如果屏幕有内容变化就去更新整个屏幕这个不仅会影响CPU性能还会影响功耗。
对于下面的场景理论上只需要更新红色区域内容即可。只在需要的时候重绘画面中变化的部分。由于基于光栅的绘图技术在数据结构上总表现为一个矩形区域且画面中变化的内容往往又被称为“弄脏了”的部分——“脏矩阵”故此得名。
脏矩阵技术的应用非常广泛例如我们所熟悉的Windows系统大部分时候就只会更新鼠标指针滑动所经过的那一小片矩形区域而已。
因为脏矩阵在降低传输带宽和CPU占用方面有着不可替代的优势几乎所有的知名GUI协议栈都在默认情况下悄悄地使用各种各样的脏矩阵算法对系统帧率进行优化。 了解脏矩阵基本背景后脏矩阵主要要解决的问题是屏幕上有哪些内容需要重绘。引用【玩转Arm-2D】如何使用脏矩阵优化帧率基础篇-腾讯云开发者社区-腾讯云的一个极端场景。
如下图显示屏从空白到显示一条直线大多数GUI框架都会重绘整个屏幕内容。 理想的脏矩阵希望是只绘制线覆盖的这部分区域但是因为脏矩阵都是矩形的所以这个奇怪的多边形是无法构建的。 那用一连串宽度Width和高度Height都为1个像素的脏矩阵来精确逼近整个斜线也就是下图这种形式理论上是可行但如何精准的找到这个这些脏矩阵呢这个需要一个特别聪明的算法本项目是做不到的。 所以通过上面分析可以发现。脏矩阵本身虽然可以有效降低刷新区域面积——提高帧率但生成脏矩阵的算法本身却可能消耗巨大。这里的矛盾在于太简陋的算法会因为一条对角线就更新整个屏幕而“想的太多”的算法也可能会因为时间成本的积累而把脏矩阵的带来的收益抵消了不少——难就难在一个度的把握上。
脏矩阵策略
从上面分析来看脏矩阵不能太智能嵌入式小设备带不动也不能说不要如何设计一个好的策略至关重要。和ARM-2D的设计理念一致与其让GUI去智能分析哪些区域需要更新不如让用户自己去告知GUI那些内容需要更新。
对于GUI而言只需要将用户告知的脏矩阵合并即可。避免作为用户是知道哪些内容是需要更新的更新的时机也完全由用户来决定这样对嵌入式设备来说问题就简化了。
在本项目中所有的控件都是用户构建的用户需要更新哪个控件的内容只需要调用egui_view_invalidate接口就会通知GUI当前控件需要更新之后GUI绘制之前会去计算所有控件的脏矩阵区域并将重叠的脏矩阵区域合并在一起最终构建一个脏矩阵列表在进行屏幕绘制时会选择PFB和脏矩阵重叠部分进行绘制。
下面针对各个场景的脏矩阵合并策略进行说明。
场景1
如下图所示这些控件之间没有重合egui_core_update_region_dirty这里判断控件和其他脏矩阵有没有重合没有重合就从egui_core.region_dirty_arr找一个空的位置记录脏矩阵的坐标信息。
最终egui_core.region_dirty_arr会有4个脏矩阵信息。 场景2
如下图所示Img0和Img1有重叠区域并且Img0和Img1都需要更新时Img0对应的脏矩阵是Dirty0.0Img1对应的脏矩阵是Dirty0.1egui_core_update_region_dirty这里会判断两个脏矩阵有重绘会通过egui_region_union将2个矩阵合并为Dirty0存入egui_core.region_dirty_arr中。
Dirty1和Dirty0无重合所以最终egui_core.region_dirty_arr中会有2个脏矩阵信息。 场景3
如下图所示Img0和Img1有重叠区域但是只有Img1需要更新时虽然2个控件重叠了但是egui_core_update_region_dirty只会保存Dirty0信息存入egui_core.region_dirty_arr中。
Dirty1和Dirty0无重合所以最终egui_core.region_dirty_arr中会有2个脏矩阵信息。 场景4
如下图所示考虑移动的场景用户调用egui_view_scroll_by或者egui_view_scroll_to接口来移动控件当新移动的位置和之前的位置没有重叠在egui_view_layout中会先将当前控件的脏矩阵信息调用egui_core_update_region_dirty更新到脏矩阵列表中新的位置通过egui_view_invalidate更新在下次layout时更新脏矩阵中。之后egui_core_update_region_dirty发现新的位置Dirty1和Dirty0没重叠两个信息都存入egui_core.region_dirty_arr中。
Dirty1和Dirty0无重合所以最终egui_core.region_dirty_arr中会有2个脏矩阵信息。 场景5
如下图所示考虑移动的场景用户调用egui_view_scroll_by或者egui_view_scroll_to接口来移动控件当新移动的位置和之前的位置有重叠时在egui_view_layout中会先将当前控件的脏矩阵信息调用egui_core_update_region_dirty更新到脏矩阵列表中新的位置通过egui_view_invalidate更新在下次layout时更新脏矩阵中。之后egui_core_update_region_dirty发现新的位置Dirty1和Dirty0有重叠两个矩阵合并存入egui_core.region_dirty_arr中。
所以最终egui_core.region_dirty_arr中只有1个脏矩阵Dirty0信息。 通过简单的处理由用户来通知脏矩阵信息相比于ARM-2D必须用户给出具体坐标信息本项目用户只需要告知GUI哪些控件的内容有变化即可GUI通过控件去构建脏矩阵列表。
脏矩阵屏幕绘制
在构建好脏矩阵信息后就需要完成屏幕绘制。由于项目绘制是按照PFB来进行的下面给出几个场景来说明脏矩阵如何实现提升刷新率的目的。
假设按行扫描下面是可能遇到的各个场景。
场景1
当PFB和脏矩阵不重叠时这个情况下这个区域无需绘制。这样就少了很多绘制动作。 场景2
当PFB包含脏矩阵时这个情况下虚线是原本需要绘制的PFB区域但是因为脏矩阵不大只需要绘制实现部分的PFB就行。这样就少了很多绘制动作。 场景3
当PFB部分包含脏矩阵时这个情况下虚线是原本需要绘制的PFB区域但是因为脏矩阵不大只需要绘制实现部分的PFB就行。这样就少了很多绘制动作。 场景4
当PFB中包含多个脏矩阵时这个情况下虚线是原本需要绘制的PFB区域但是因为两个脏矩阵不重叠原本一次绘制需要变成2次绘制PFB0绘制1次FPB1绘制1次。这样就少了很多绘制动作。 脏矩阵无法解决的场景
开篇说的画线的极端场景是无法优化的。
此外在支持触控的场景中显示帧率性能并不能通过脏矩阵方案提升如下所示场景有2个图片Img1和Img2从右滑动到左边时整个屏幕的内容还是需要重绘。
所以说脏矩阵并不是万能的部分场景还是得一个个去挖掘CPU性能。