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

本文介绍了如何在Android系统中实现实时帧率(FPS)的计算,主要通过SurfaceFlinger的FrameTimeline类获取各layer的刷新率,并利用RefreshRateOverlay类在UI上动态显示。作者还分享了相关的代码和购买课程获取更多信息的链接。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景:

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数据

在这里插入图片描述

更多framework干货请关注“千里马学框架”

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

千里马学框架

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

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

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

打赏作者

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

抵扣说明:

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

余额充值