Android 显示surfaceFlinger vsync 获取

vsync 的概念

vsync简单理解就是一帧图像在显示设备这边显示完成之后(图像从左上角扫描到了右下角了) 发送的第一个硬件vsync信号, 显示设备重新回到左上角开始显示的时候会在发第二个vsync信号。在发送第一个vsync信号出来的时候,上层要开始准备合成处理好的图像buffer。而且这个必须在下一个vsync到达之前准备完成 否则显示会出现异常。 vsync 信号主要应用app刷新,视频显示刷新。

问题:

  1. vsync信号是硬件发出的,那上层应该怎么去获取?
  2. vsync 如何从底层传递到应用?

vsync应用层获取的方式

网上资料,有些太旧运行不了,最好的参考的代码是google的源码的test。

  • google 参考方法

    源码位置:frameworks\native\services\surfaceflinger\tests\vsync\vsync.cpp

简要流程:硬件的vsync抽象在上层是一个fd。当有vsync的时候,上层looper会调用receiver 回调,在回调中就可以获取到count 和timestamp。回调函数必须是 下面三个参数这样的。

int receiver(int /*fd*/, int /*events*/, void* data)

addFd 将displayEvent的fd、要添加的事件也即有事件输入,有事件之后的回调函数,disPlayEvent自身(用于传递到回调函数获取)

实现时需要创建一个线程,在线程中队DisplayEventReceiver的fd进行pollOnce 操作。
fd没有poll_input的消息时,线程会堵塞。会消息的时候pooll返回 然后调用回调函数receiver,在receriver可以获取vysnc的count和timestamp。

    DisplayEventReceiver myDisplayEvent;
    sp<Looper> loop = new Looper(false);
    loop->addFd(myDisplayEvent.getFd(), 0, ALOOPER_EVENT_INPUT, receiver, &myDisplayEvent);

int receiver(int /*fd*/, int /*events*/, void* data) {
    DisplayEventReceiver* q = (DisplayEventReceiver*)data;
    ssize_t n;
    DisplayEventReceiver::Event buffer[1];
    static nsecs_t oldTimeStamp = 0;
    while ((n = q->getEvents(buffer, 1)) > 0) {
        for (int i = 0; i < n; i++) {
            ALOGD("buffer[i].header.type is :%d \n", buffer[i].header.type);
            if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
                ALOGD("event vsync: count=%d\t", buffer[i].vsync.count);
            }
            if (oldTimeStamp) {
                float t = float(buffer[i].header.timestamp - oldTimeStamp) / s2ns(1);
                ALOGD("%f ms (%f Hz)\n", t * 1000, 1.0 / t);
            }
            oldTimeStamp = buffer[i].header.timestamp;
        }
    }
    return 1;
}

vsync 信号传递

vsync 从hwc 获取到之后 回调到surfaceflinger, surfaceFlinger 通过socket发送到应用。

  • 应用注册fd到surfacefinger流程

    主要在DisplayEventReceiver构造函数中实现。

    sp<ISurfaceComposer> sf(ComposerService::getComposerService());
    if (sf != nullptr) {
        mEventConnection = sf->createDisplayEventConnection(vsyncSource, eventRegistration);
        if (mEventConnection != nullptr) {
            mDataChannel = std::make_unique<gui::BitTube>();
            mEventConnection->stealReceiveChannel(mDataChannel.get());
        }
    }

构造函数流程:

  1. 获取surfaceflinger的服务。
  2. 通过surfaceflinger的createDisplayEventConnection的函数创建一个gui::BitTube对象,
    gui::BitTube管理一对无名的socket, 这个socket会对BitTube的mReceived 和 mSendFd
    进行初始化。
  3. 应用端也会创建一个gui::BitTube,并传递到surfaceflinger中,surfaceflinger 中将已经创建好的BitTube中mReceived赋值给外部创建好BitTube中的mReceived。
    这样外部应用端和surfaceFlinger建立了连续。发送到surfaceflinger BitTube的mSendFd的消息,应用端可以监听并接收。

DisplayEventDispatcher继承自LooperCallback,看LooperCallback的实现可以知道addFd
的有INPUT的event后回调到的是handleEvent。

class DisplayEventDispatcher : public LooperCallback

    if (mLooper != nullptr) {
        int rc = mLooper->addFd(mReceiver.getFd(), 0, Looper::EVENT_INPUT, this, NULL);
        if (rc < 0) {
            return UNKNOWN_ERROR;
        }
    }

  • surfaceFlinger 注册vsync回调到hwc以及 回调上报的路径
  1. 首先hwc是一个hal层的服务 其接口定义在这个目录 hardware/interfaces/graphics/composer/2.1。其对应的service 是android.hardware.graphics.composer@2.1-service。 surfaceflinger提供这个composer的service提供的接口 可以注册回调到hwcomposer 的hal层中。
mCompositionEngine->getHwComposer().setCallback(this);

 mComposer->registerCallback(
            sp<ComposerCallbackBridge>::make(callback, mComposer->isVsyncPeriodSwitchSupported()));


void Composer::registerCallback(const sp<IComposerCallback>& callback)
{
    android::hardware::setMinSchedulerPolicy(callback, SCHED_FIFO, 2);
    auto ret = [&]() {
        if (mClient_2_4) {
            return mClient_2_4->registerCallback_2_4(callback);
        }
        return mClient->registerCallback(callback);
    }();
    if (!ret.isOk()) {
        ALOGE("failed to register IComposerCallback");
    }
}

而在hal层的 vsync的实现各不相同。 有一种实现方式运行一个线程,然后在线程中使用
drmWaitVBlank等待vsync,vsync产生后回调到之前surfaceflinger 注册进来的callback中。

在surfaceflinger中会创建一个DispSyncThread线程,这个线程收到vsync事件后也就是回调到onComposerHalVsync中时。通过之前注册进来的EventThread的callback
构造了一个DisplayEventReceiver::Event类型事件,类型为DISPLAY_EVENT_VSYNC,还有displayId,时间戳以及接收到的次数。构造好之后会唤醒EventThread线程,这个线程从mPendingEvents中的事件调用dispatchEvent将事件分发给监听者,监听者即是向EventThread请求了Vsync的EventThreadConnection并addfd的配置回调函数的。

void SurfaceFlinger::onComposerHalVsync(hal::HWDisplayId hwcDisplayId, int64_t timestamp,
                                        std::optional<hal::VsyncPeriodNanos> vsyncPeriod)
    mScheduler->addResyncSample(timestamp, vsyncPeriod, &periodFlushed);

参考链接:
https://blog.csdn.net/qq_34211365/article/details/105123790

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: SurfaceFlingerAndroid系统中的一个重要组件,负责管理和显示所有的图形界面。它的显示流程如下: 1. 应用程序创建一个Surface对象,将图形数据发送给SurfaceFlinger。 2. SurfaceFlinger将图形数据存储在一个称为SurfaceTexture的缓冲区中。 3. SurfaceFlinger使用OpenGL ES对图形数据进行处理和渲染。 4. SurfaceFlinger将渲染后的图像发送到显示器。 5. 如果有多个应用程序同时发送图形数据,SurfaceFlinger会根据优先级和Z轴深度对它们进行排序和合成。 6. 最终,SurfaceFlinger将所有图形数据合成为一个图像,并将其显示在屏幕上。 总之,SurfaceFlingerAndroid系统中的一个非常重要的组件,它负责管理和显示所有的图形界面,保证了Android系统的流畅性和稳定性。 ### 回答2: SurfaceFlingerAndroid的图形渲染引擎,负责掌控所有图形对象的显示。下面是SurfaceFlinger显示流程。 1. 确定显示设备:SurfaceFlinger首先要确定使用哪个硬件设备来显示图像。 2. 提取图形对象:SurfaceFlinger会提取界面中包含的所有图形对象,这些对象可以是应用程序创建的窗口,也可以是系统悬浮窗、状态栏、壁纸等。 3. 图形对象组装:SurfaceFlinger会将所有被提取的图形对象组装成层(layer),按照层级关系维护图形对象的顺序。 4. 图形对象合成:SurfaceFlinger会使用OpenGL ES对所有层进行合成,生成一张完整的帧缓存。 5. 帧缓存提交:SurfaceFlinger将生成的帧缓存提交给硬件设备进行显示。 整个显示过程中,SurfaceFlinger还负责处理窗口跨越的动画效果,以及处理图形对象的动态增加或删除等情况。 需要注意的是,在上述流程中,层级关系对于图形对象的显示非常重要。较上层的对象会覆盖掉较下层的对象,这个特性在界面中用于实现窗口的遮挡和浮动效果。而不同的层级可以有不同的属性,例如透明度等,这些属性也会影响它们在合成帧缓存时的表现。此外,每个图形对象在SurfaceFlinger内部都会有一个对应的Surface对象,Surface对象内部保存了该图形对象的像素数据,SurfaceFlinger会使用这些数据进行图形对象的合成和显示。 ### 回答3: SurfaceFlingerAndroid操作系统用于显示图形的一个重要组件,它负责管理系统中所有显示的界面,包括应用程序UI、系统UI、动画效果及其它与显示相关的任务。下面我们简单介绍一下SurfaceFlinger的工作流程。 SurfaceFlinger在系统启动时便会启动,它通过系统调用EGL创建一个屏幕缓冲区(framebuffer),这个缓冲区是硬件加速的显存空间,它用于显示内容。应用程序或系统UI产生的每一个图形子集必须是基于帧缓冲区中的Surface对象,这些Surface对象可以是不同应用或UI组件的输出。这些输出通常是在本地内存中被创建或花费大量的CPU时间计算,但是它们最终都会被发送到SurfaceFlinger进行显示处理。 在处理单个图形子集之前,SurfaceFlinger使用双缓冲技术来管理整个帧缓冲区的更新。当一帧完全渲染后,SurfaceFlinger直接交换当前帧缓冲区与另一个缓冲区的指针,实现页面刷新的无缝过渡。这种技术可以避免一些出现残影和撕裂的问题。 处理一个图形子集通常分为三个阶段:更新、合并和显示。在更新阶段,渲染线程会对传入的图形数据进行处理,并将其写入屏幕缓冲区的一个Surface中。在合并阶段,SurfaceFlinger会将所有正在显示Surface的像素数据合并到屏幕缓冲区的输出Surface中,并应用混合和过滤效果。最后,在显示阶段,渲染引擎会将输出Surface中的像素数据转发到帧缓冲区中,然后输出到屏幕上显示给用户。 除了处理图形子集外,SurfaceFlinger还负责处理用户输入,并将其传递给正在显示的应用程序或UI组件。用户输入通常包括触摸事件、按键事件、语音输入和手写输入等。 总之,SurfaceFlingerAndroid系统中一个重要且复杂的组件,担负着管理和协调所有显示图像的任务,对于保证用户体验和操作流畅度起到了至关重要的作用。每个应用程序与SurfaceFlinger交互时,必须要遵循先进先出的原则,并且应用程序中应该尽可能地减少对SurfaceFlinger的请求,以保证更高的流畅度和性能。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值