View绘制上屏流程

App显示在屏幕上完整流程:

android12开始,producer,consumer,BufferQueue以及Buffer的dequeue,queue,acquire,release都从SurfaceFlinger移到了App端实现,如下图

View上屏流程:

  • view.invalidate/requestlayout发出绘制请求
  • vsync会触发绘制请求任务(uithread调用syncframestate把界面元素传递给RenderThread生成displaylist)
  • RenderThread调用opengl接口把displaylist绘制成像素放到graphicbuffer,然后再调用queuebuffer放到App的bufferqueue(release fence)

App queueBuffer→ frameAvailableListener.onFrameAvailable→BufferQueueConsumer::processNextBufferLocked

binder通知SurfaceFlinger.BufferQueueConsumer::acquireBuffer 获取一个graphicbuffer调用SurfaceComposerClient::Transaction.setBuffer保存到surfaceflinger layer中,并向hwc发送vsync请求

  • SurfaceFlinger在下一个vsync到来后询问hwc每个layer是否需要gpu合成
  1. gpu合成:renderengine模块把所有window的bufferqueue调用aquirebuffer拿到要合成buffer,调用gpu合成之后放到framebuffer,hwc再根据framebuffer合成1个layer走device合成过程,并释放fence( gpu合成原理是通过拿到可用buffer合成帧数据放到framebufferlayers合成_surfaceflinger 合成是通过hwc还是gpu-优快云博客
  2. device合成:layer直接透传到hwc,透传给display,display从每个layer的bufferqueue中读取像素显示到屏幕

SurfaceFlinger消费bufferqueque

onVsync -> SurfaceFlinger::onMessageInvalidate() -> BufferLayer::latchBuffer() -> BufferQueueLayer::updateTexImage() 

{

    BufferLayerConsumer::acquireBufferLocked() 
   BufferLayerConsumer::updateAndReleaseLocked

}

  • Surfaceflinger RenderEngine负责把每个texture合成生成framebuffer之后交给hwc消费

SkiaGLRenderEngine.cpp文件在native/libs/renderengine 目录下
drawlayers方法负责将所有layers的buffer描画到屏幕的framebuffer中,drawlayers方法在描画中,会根据layerSettings的具体信息为各个layer添加某些显示特效(例如圆角窗口,窗口阴影,高斯模糊效果)

多个App在屏幕上显示流程:

1个App Window从SurfaceFlinger申请1个surface时,会创建1个window对应的BufferQueue,每个BufferQueue包含3个buffer(SF合成图像也是在Gpu完成的)

关键流程

一,App完成1帧数据时把生产的buffer通过binder传给SurfaceFlinger去消费

 queueBuffer→frameAvailableListener.onFrameAvailable

→BufferQueueConsumer::processNextBufferLocked→BufferQueueConsumer::acquireBuffer

(像app要buffer来消费)

→BLASTBufferQueue#SurfaceComposerClient::Transaction.setBuffer(mSurfaceControl, buffer, releaseCallbackId, releaseBufferCallback)

二,SurfaceFlinger消费完之后releasebuffer

Surfaceflinger E TransactionCallbackInvoker: TransactionCallbackInvoker ITransactionCompletedListener onTransactionCompleted
Surfaceflinger E ITransactionCompletedListener:onTransact BpTransactionCompletedListener onTransactionCompleted
Client ITransactionCompletedListener: -----------------------onTransact BnTransactionCompletedListener onTransactionCompleted
Client BLASTBufferQueue: releaseBufferCallbackThunk→ProducerListener.onBufferReleased()
Client BufferQueueConsumer: [SurfaceView[com.jidu.rearscreen/com.jidu.rearscreen.MainActivity]#1(BLAST Consumer)1]
Client releaseBuffer: releasing slot 0

调用stack如下

BufferQueueConsumer: stackdump:#00 pc 000580ff  /system/lib/libgui.so (android::BufferQueueConsumer::releaseBuffer(int, unsigned long long, android::sp<android::Fence> const&, void*, void*)+130)
BufferQueueConsumer: stackdump:#01 pc 00059117  /system/lib/libgui.so (android::BufferQueueConsumer::releaseBuffer(int, unsigned long long, void*, void*, android::sp<android::Fence> const&)+30)
BufferQueueConsumer: stackdump:#02 pc 00076d27  /system/lib/libgui.so (android::ConsumerBase::releaseBufferLocked(int, android::sp<android::GraphicBuffer>, void*, void*)+134)
BufferQueueConsumer: stackdump:#03 pc 0007580d  /system/lib/libgui.so (android::BufferItemConsumer::releaseBuffer(android::BufferItem const&, android::sp<android::Fence> const&)+140)
BufferQueueConsumer: stackdump:#04 pc 0006c467  /system/lib/libgui.so (android::BLASTBufferQueue::releaseBufferCallback(android::ReleaseCallbackId const&, android::sp<android::Fence> const&, unsigned int, unsigned int)+1362)
BufferQueueConsumer: stackdump:#05 pc 0006d827  /system/lib/libgui.so (android::releaseBufferCallbackThunk(android::wp<android::BLASTBufferQueue>, android::ReleaseCallbackId const&, android::sp<android::Fence> const&, unsigned int, unsigned int)+62)
BufferQueueConsumer: stackdump:#06 pc 0007039b  /system/lib/libgui.so (std::__1::__function::__func<std::__1::__bind<void (&)(android::wp<android::BLASTBufferQueue>, android::ReleaseCallbackId const&, android::sp<android::Fence> const&, unsigned int, unsigned int), android::wp<android::BLASTBufferQueue>, std::__1::placeholders::__ph<1> const&, std::__1::placeholders::__ph<2> const&, std::__1::placeholders::__ph<3> const&, std::__1::placeholders::__ph<4> const&>, std::__1::allocator<std::__1::__bind<void (&)(android::wp<android::BLASTBufferQueue>, android::ReleaseCallbackId const&, android::sp<android::Fence> const&, unsigned int, unsigned int), android::wp<android::BLASTBufferQueue>, std::__1::placeholders::__ph<1> const&, std::__1::placeholders::__ph<2> const&, std::__1::placeholders::__ph<3> const&, std::__1::placeholders::__ph<4> const&> >, void (android::ReleaseCallbackId const&, android::sp<android::Fence> const&, unsigned int, unsigned int)>::operator()(android::ReleaseCallbackId const&, android::sp<android::Fence> const&,
BufferQueueConsumer: stackdump:#07 pc 000a7d47  /system/lib/libgui.so (android::TransactionCompletedListener::onTransactionCompleted(android::ListenerStats)+3382)
BufferQueueConsumer: stackdump:#08 pc 000925a5  /system/lib/libgui.so (int android::SafeBnInterface<android::ITransactionCompletedListener>::callLocalAsync<void (android::ITransactionCompletedListener::*)(android::ListenerStats)>(android::Parcel const&, android::Parcel*, void (android::ITransactionCompletedListener::*)(android::ListenerStats))+204)
BufferQueueConsumer: stackdump:#09 pc 00028ddb  /system/lib/libbinder.so (android::BBinder::transact(unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+162)
12-15 10:46:54.793667  2959  3319 E BufferQueueProducer: [SurfaceView[com.jidu.renderframe/com.jidu.renderframe.MainActivity]#1(BLAST Consumer)1](id:b8f00000001,api:1,p:2959,c:2959) queueBuffer: slot=0/19261 time=652049692092 dataSpace=0 validHdrMetadataTypes=0x0 crop=[0,0,0,0] transform=0 scale=SCALE_TO_WINDOW
12-15 10:46:54.793705  2959  3319 E BufferQueueConsumer: [SurfaceView[com.jidu.renderframe/com.jidu.renderframe.MainActivity]#1(BLAST Consumer)1](id:b8f00000001,api:1,p:2959,c:2959) acquireBuffer: acquiring { slot=0/19261 buffer=0x74f1a1b440 } notify_all  queuesize:1

12-15 10:46:54.802876  2959  3319 E BufferQueueProducer: [SurfaceView[com.jidu.renderframe/com.jidu.renderframe.MainActivity]#1(BLAST Consumer)1](id:b8f00000001,api:1,p:2959,c:2959) dequeueBuffer

12-15 10:46:54.742224  2959  3028 E BufferQueueConsumer: [SurfaceView[com.jidu.renderframe/com.jidu.renderframe.MainActivity]#1(BLAST Consumer)1](id:b8f00000001,api:1,p:2959,c:2959) releaseBuffer: releasing slot 2 DequeueCondition.notify_all
源码如下:
    void onReleaseBuffer(ReleaseCallbackId callbackId, sp<Fence> releaseFence,
                         uint32_t transformHint, uint32_t currentMaxAcquiredBufferCount) override {
                         
        callRemoteAsync<decltype(
                &ITransactionCompletedListener::onReleaseBuffer)>(Tag::ON_RELEASE_BUFFER,
                                                                  callbackId, releaseFence,
                                                                  transformHint,
                                                                currentMaxAcquiredBufferCount);
}

releaseBuffer流程:

BufferStateLayer::~BufferStateLayer onReleaseBuffer
12-25 21:00:18.606   603   603 E ITransactionCompletedListener: -----------------------onTransact BpTransactionCompletedListener onTransactionCompleted
12-25 21:00:18.606 12674 14754 E ITransactionCompletedListener: -----------------------onTransact BnTransactionCompletedListener onTransactionCompleted
12-25 21:00:18.606 12674 14754 E BLASTBufferQueue: releaseBufferCallbackThunk    BufferQueueConsumer:releaseBuffer: releasing slot x

Systrace全流程:

  1. App绘制到dequeue到buffer
  2. Consumer aquirebuffer之后把buffer设置给Surfaceflinger
  3. Surfaceflinger 消费完了 releaseBuffer

关键概念:

  • sf合成layer方式:优先硬件合成,合成失败才用gpu合成兜底

1种:hwc(高通开发的屏幕芯片dpu做)硬件合成,但是不能合成alpha,高斯模糊这种复杂图像

1种:soft (client/gpu)不会出错, cpu占用高

  • SurfaceFlinger的线程:acquire,queue,dequeue采用主线程,releaseBuffer采用子线程
  • BBQ(BufferQueue的增强类BlastBufferQueue)【BufferQueue中是BufferSlot来保存Buffer状态,1个Buffer有四种状态: Dequeued, Queued, Acquired, Free】
  • QueuedBuffer - X                  生产者队列,sf会从这个队列中获取buffer
  • BLAST Consumer - X           消费者队列
  • SurfaceFlinger为每个surface创建的BufferStateLayer,封装在mSurfaceControl暴露给客户端,mSurfaceControl中新建了BLASTBufferQueue
  • BLASTBufferQueue分别又创建BufferQueueCore,BufferQueueProducerBufferQueueConsumer持有相同的BufferQueueCore:
  • BufferQueueCore是graphicbuffer存储的数据结构,包含如下2个变量:

    mSlots:包含了默认大小为64的BufferSlot数组,但一个surface默认初始化3个buffrer,

    mQueue :BufferItem类型的数组,生产者和消费者按照Fifo规则消费queque中的数据

    Producer调用queueBuffer后会修改mSlots,mQueue(但不知道这2个的区别在哪里)

    BufferSlot是1个graphicbuffer封装,成员变量有mGraphicBuffer,mBufferState(buffer的状态是free,queued,aquired,dequeue), mFence(前主人是否用完的标志),SurfaceTexture可以对Graphic Buffers做自定义特效处理

  • 将图形内存Graphic Buffer送到LCD显示的2种方法:gpu合成gralloc.post()和hwcomposer的硬件合成
  • 从view.invalide()提交绘制请求到display显示至少隔3帧(一个surface和SurfaceFlinger有3个buffer轮流使用)
  • dequeueBuffer阻塞之后有timeout(默认是4s) W OpenGLRenderer: dequeueBuffer failed, error = -110; switching to fallback
  • 关于dequeueBuffer等buffer相关bug,搜索:SurfaceFlinger,dequeueBuffer关键字
  • fence机制:fence对象通过fd在3个进程之间共享
  • 释放fence时机:App在gpu绘制一帧完毕,SurfaceFlinger在updateTexImage,HWC在合成完毕(HWC合成开始前提是gpu和device合成用到的fence都可用)
  • 错误汇总
  • 04-20 15:05:56.217276   597   597 E SurfaceFlinger: Attempted to create an ExternalTexture for layer lrc#0 that exceeds render target size limit.
  • 12-14 15:55:53.495030   583   583 E BpTransactionCompletedListener: Failed to transact (-2147483646)   surfaceflinger通知释放buffer失败了
  • RenderThread: BufferQueueProducer: setDequeueTimeout:4000(

    但注意!UnityMain  Thread:一直阻塞不会Timeout,BufferQueueProducer: [SurfaceView[com.cottongame.triangleAdventure.jidu/com.unity3d.player.MainActivity]#1(BLAST Consumer)1]

  • trace分析卡顿,Davey! duration主线程卡顿

debuyg测试surfaceflinger方法

编译:make surfaceflinger

替换车机中的文件:将out/target/product/msmnile_gvmq/system/bin/surfaceflinger 文件

替换车机中的system/bin/surfaceflinger文件

重启Android系统:adb shell reboot

参考文献

aosp源码路径 Android/lagvm/LINUX/android/frameworks/native/libs/gui#

native/services/surfaceflinger/

android app渲染流水线图解

surface  Android 图形系统之 SurfaceTexture

Android 图形图像 - 随笔分类 - 二的次方 - 博客园

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值