离屏渲染

为什么出现离屏渲染

是否离屏渲染是通过下面的属性进行判断执行的。

​ bool promotedToLayer() const {

​ return mLayerProperties.mType == LayerType::None && fitsOnLayer() &&

​ (mComputedFields.mNeedLayerForFunctors || mLayerProperties.mImageFilter != nullptr ||

​ mLayerProperties.getStretchEffect().requiresLayer() ||

​ (!MathUtils::isZero(mPrimitiveFields.mAlpha) && mPrimitiveFields.mAlpha < 1 &&

​ mPrimitiveFields.mHasOverlappingRendering));

​ }

​ LayerType effectiveLayerType() const {

​ return CC_UNLIKELY(promotedToLayer()) ? LayerType::RenderLayer : mLayerProperties.mType;

​ }

  1. 在检查home在文件夹多层模糊的场景下,存在离屏的layer和透明背景,见8.22三层模糊+动态阴影性能测试分析
  2. 侧边栏在动画过程中alpha值会从0变化到1,此时mHasOverlappingRendering没有重写,所以造成离屏绘制,因为surface的绘制区域较小,所以对他的child绘制的miui阴影造成了裁切问题,jira见BUGOS2-45760,侧边栏通过重写hasOverlappingRendering方法为false,可以实现动画过程中不对layer进行离屏绘制。相关patch见:https://gerrit.pt.mioffice.cn/c/platform/packages/apps/SecurityCenter/+/4394489

参考: https://xiaomi.f.mioffice.cn/docx/doxk4HEqsVu7EjAeM2o78WrVHTc

父布局中设置 View不进行绘制裁剪会扩大渲染面积,降低性能

如下代码:

android:clipChildren="false"
android:clipToPadding="false"

上面的代码是设置不进行绘制裁剪,可以让父布局中的子控制绘制可以超出父容器的范围

androidViewGroup代码如果不显示设置默认是裁剪的,即如下代码和不设置是相同效果的

android:clipChildren="true"
android:clipToPadding="true"

修改后的代码在现象上会出现view不裁剪问题,不裁剪后

TODO 增加一个Demo进行演示

出现离屏渲染的原因

View在做动画或者view alpha在(0,1)之间,此时可能存在离屏控价

确认离屏渲染

  • 打开开发者选项中的显示硬件层更新,复现问题,查看动画过程中是否存在闪绿色的情况,如果存在闪绿色的情况,则存在离屏渲染。

参考:https://xiaomi.f.mioffice.cn/docx/doxk4G1OaiEMJ8PgvEnliwR8GDf

怎么规避离屏渲染

所以针对自定义View(闪绿色区域对应的layout或者View)需要重写hasOverlappingRendering方法来避免离屏渲染。

 
class view{
    ....
        
 	@Override
    public boolean hasOverlappingRendering() {
        return false;
    }
}    
    

API24中增加了一个强制设置OverlappingRendering的方法,所以可以通过

forceHasOverlappingRendering()方法设置为false,也可以在xml中设置为false。