GUI刷新机制研究(三) 脏区计算
回到我们刚才看到的调用栈:
CoreRoot_UpdateGE20
CoreRoot_UpdateCanvas
CoreGroup_drawContent
ViewsRectangle_Draw
现在我们比较感兴趣的地方在于,CoreRoot是如何判断脏区数目以及,到底是怎么按照脏区来更新的。
回到CoreRoot_UpdateGE20, 上来先调用了CoreRoot_BeginUpdate来对CoreRoot进行脏区数目的判断。
所以我们暂时先把目光转向这里面一探究竟:
首先是两个bool变量,分别是preserveFrameBufferContent 和 fullScreenUpdate
可以看到这里主要是用来标记GUI每一帧的刷新方式,具体是在哪里定义的呢,
发现在ew的ewgfxdefs.h 中由一些#if 的条件来判断,一通操作下来,EW_PRESERVE_FRAMEBUFFER_CONTENT是1
==================================================
真正的关键在于 CoreGroup_InvalidateArea, 我们是在这里强行指定一个Invalid区域才影响到后面真正的脏区计算的
所以这里也要深入分析一下:
这个函数里面有一点递归的算法在里面,首先是对判断当前的CoreGroup的super2.owner是否为0,如果为0,说明已经层层遍历到自己的root上了
因此这里是递归return的地方【这里是为啥是super2还没有看的太清楚】
好的,如果没有到return的条件里,那么就进行以下的处理,首先从当前GraphicsCanvas中拿到上一帧 的invalidateArea, 然后与传入的Area做一个union得到一个新的Area, 如果新的Area和旧的Area不相等,那么就EwNotifyObjObservers((XObject)grp, 0) 以及EwNotifyObjObservers((XObject)buf, 0) 这里找到objObserbers中的grp和buf,直接触发对应的slot.
slot是通过EwAttachObjObservers注册的, 通过搜索,找到其中一个注册地在Views.c中,以其中一个ViewsImage_timerSlot为例
这个对应的就是应用层的Views::Image.timerSlot, 这个Slot里面就是判断一些用户操作或者根据定时器判断当前是否要InvalidateArea
这里所有人都在对自己的super2.owner进行判断,循环一次后也是令grp = grp->Super2.owner 然后再去InvalidateArea
Views.c中很多类似的代码,就是用来处理和视效相关代码,比如ViewsText_OnSetColorBL 里面就是修改一个颜色,然后invalidateArea
==================================================================================================
发现一个事情,CoreGroup里面没有 noOfRegions + 1的操作, 在CoreRoot里面有这个操作,所以,中间一定是以某种方式走到了
CoreRoot_InvalidateArea 这里面。打了一些trace发现了一些端倪
EwProcessSignals
XFlatHorzBarSlider_UpdateViewState
CoreRectView_OnSetBounds
CoreRoot_InvalidateArea
================================================================================================
CoreRoot_UpdateGE20
CoreRoot_BeginUpdate
CoreRoot_InvalidateArea
===============================================================
所以真正的关键在于CoreRoot_InvalidateArea
这里面也的确是真正的计算了脏区的数目,大致就是每传入一个area, 就和之前已经记录的脏区测试是否相交
如果相交,那么脏区做union, 个数不变,如果全部没有交集,那么看一下脏区的个数只要小于4,就可以直接+1
超过4的话就选择和其中某一个做一个union。
========================================
到了CoreRoot_BeginUpdate 结束,本地绘制的脏区实际个数和大小,也就真正算完了。
下面就是CoreRoot_UpdateCanvas里面的活了