实时刷新率Fps实现相关知识讲解

背景:

hi,粉丝朋友们:
大家好!上次视频发布了一个实时fps的实现成果展示如下:
在这里插入图片描述
相关介绍视频如下:
https://mp.weixin.qq.com/s/CvQ3-MlEHAC-Wez7pCiuIg

下面就来开始介绍一下这个实时fps实现的两个核心部分
在这里插入图片描述
分为实时fps的计算,也就是最核心的部分,再接下来是如何展示fps的ui数字

实时fps帧率的计算

在SurfaceFlinger中FrameTimeline类中有一个现成的计算fps的方法如下:

//重点参数就是layerIds,这个代表就是每个layer即每个task的图层的id,即该接口是统计每个layer的对于刷新率
float FrameTimeline::computeFps(const std::unordered_set<int32_t>& layerIds) {
    if (layerIds.empty()) {
        return 0.0f;
    }
    std::vector<nsecs_t> presentTimes;
    {
        std::scoped_lock lock(mMutex);
        //初始化话presentTimes这个集合
        presentTimes.reserve(mDisplayFrames.size());
        //遍历当前系统中所有的mDisplayFrames数据
        for (size_t i = 0; i < mDisplayFrames.size(); i++) {
            const auto& displayFrame = mDisplayFrames[i];
            if (displayFrame->getActuals().presentTime <= 0) {
                continue;
            }
            //获取每个DisplayFrame的对应surfaceFrame
            for (const auto& surfaceFrame : displayFrame->getSurfaceFrames()) {
            //如果该surfaceFrame已经处于Presented已经显示,而且刚好layerIds又是属于要计算的
                if ((surfaceFrame->getPresentState() == SurfaceFrame::PresentState::Presented &&
                    layerIds.count(surfaceFrame->getLayerId()) > 0 )) {
                    // We're looking for DisplayFrames that presents at least one layer from
                    // layerIds, so push the present time and skip looking through the rest of the
                    // SurfaceFrames.
                    //把displayFrame的presentTime时间放入到了presentTimes集合
                    presentTimes.push_back(displayFrame->getActuals().presentTime);
                    break;
                }
            }
        }
    }

    // FPS can't be computed when there's fewer than 2 presented frames.
    if (presentTimes.size() <= 1) {
        return 0.0f;
    }

    nsecs_t priorPresentTime = -1;
    nsecs_t totalPresentToPresentWalls = 0;
//遍历前面的presentTimes集合
    for (const nsecs_t presentTime : presentTimes) {
        if (priorPresentTime == -1) {
            priorPresentTime = presentTime;//首先获取了第一个presentTime作为基点
            continue;
        }
		//开始统计所有绘制帧的总时间
        totalPresentToPresentWalls += (presentTime - priorPresentTime);
        priorPresentTime = presentTime;
    }
    //1秒的时间变成ns
    const constexpr nsecs_t kOneSecond =
            std::chrono::duration_cast<std::chrono::nanoseconds>(1s).count();
    // (10^9 nanoseconds / second) * (N present deltas) / (total nanoseconds in N present deltas) =
    // M frames / second
    //这里是核心计算公式,直接看肯定比较难懂,转换成更好理解公式
    //perFrameTime =totalPresentToPresentWalls  / (presentTimes.size() - 1) 
    //这个代表过去一段时间内,平均每一帧花费时间,1秒时间 / perFrameTime = 一秒绘制的帧数fps
    return kOneSecond * static_cast<nsecs_t>((presentTimes.size() - 1)) /
            static_cast<float>(totalPresentToPresentWalls);
}

代码其实还算不太难,主要分为以下几个部分:
1、统计出对应layerID的已经处于已经显示的presentTimes的集合
2、根据统计的presentTimes的集合,计算出相关的总耗时
3、根据计算公式计算出来了一秒钟的平均可以绘制的fps

实时fps帧率的ui展示

说说线索,首先就是android系统其实自带了一个刷新的显示按钮,不过这个刷新率是静态的,他只是来展示一下手机屏幕的刷新率,因为目前很多手机都是支持多种刷新率,比如120-60hz都是支持的,所以这样就可能目前屏幕的刷新率可以有不同档次,所以这个刷新率按钮主要就是显示一下目前手机的刷新情况而已,并不是说统计帧手机系统每个画面的实时刷新率,即这个按钮开启后,只是永远固定显示手机刷新率比如60,90,120
在这里插入图片描述
开启后如下:
在这里插入图片描述
所以就是顺着这条思路去探索,这个数字如何显示的。

具体追查到的结果如下:
核心代码路径:
frameworks/native/services/surfaceflinger/RefreshRateOverlay.h
frameworks/native/services/surfaceflinger/RefreshRateOverlay.cpp
在这里插入图片描述
其实本质上就是建立了一个顶部图层,然后用这个图层绘制相关数字:
在这里插入图片描述
dump出来也是一样的:
在这里插入图片描述

总结方案

1、利用FrameTimeLine来获取实时fps的数据
2、直接使用SurfaceFlinger中的RefreshRateOverlay这个图层类来负责显示这个实时fps数据

在这里插入图片描述

本文章更多详细代码和资料需要购买课程获取
hal+perfetto+surfaceflinger
https://mp.weixin.qq.com/s/LbVLnu1udqExHVKxd74ILg
在这里插入图片描述

私聊作者+v(androidframework007)

其他课程七件套专题:在这里插入图片描述
点击这里
https://mp.weixin.qq.com/s/Qv8zjgQ0CkalKmvi8tMGaw

视频试看:
https://www.bilibili.com/video/BV1wc41117L4/

  • 25
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千里马学框架

帮助你了,就请我喝杯咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值