Android -- SurfaceFlinger 合成主线程 系列 (三)

SurfaceFlinger 属于system_server进程,在system_init.cpp中利用SurfaceFlinger::instantiate()启动,在此加入到service manager中,所以本身提供service服务功能。


首先看下SurfaceFlinger的类声明:

class SurfaceFlinger :
        public BinderService<SurfaceFlinger>,
        public BnSurfaceComposer,
        protected Thread



从接口可以看出使用Binder与客户端通讯,并且继承线程 Thread 类,则循环执行threadLoop。完成系统中的各个Layer-Surface进行混合,然后将一帧帧混合好的图像传送到显示framebuffer中。


其主线程工作流程图如下:




下面就这以上图五步将代码一一过一遍:
1、waitForEvent() 等待什么事情呢?


void SurfaceFlinger::waitForEvent()
{
    while (true) {
     ......
    
       sp<MessageBase> msg = mEventQueue.waitMessage(timeout);
     ......
        if (msg != 0) {
            switch (msg->what) {
             //等的就是这个消息事件哟。。。。
                case MessageQueue::INVALIDATE:
                    // invalidate message, just return to the main loop
                    return;
            }
        }    
  }
}



原来是等待收到MessageQueue::INVALIDATE重绘消息才退回到主线程,那么这个消息由谁来发送呢?


请看下面代码:

void SurfaceFlinger::signalEvent() {
    mEventQueue.invalidate();
}


void SurfaceFlinger::signal() const {
    // this is the IPC call
    const_cast<SurfaceFlinger*>(this)->signalEvent();
}


这是就是发送消息的点,这个函数signalEvent由谁来调用呢?其个这个发起都是上一节说的,在释放Surface对应的显示缓冲区需要显示时调用:
unlockAndPost() --> queueBuffer() --> mClient.signalServer() --> SurfaceFlinger::signal()


2、handlePageFlip()  
该阶段会遍历各个Layer,在每个Layer中,取得并锁住该Layer的frontBuffer,然后利用frontBuffer 中的图像数据生成该Layer的2D贴图(Texture),并且计算更新区域,为后续的混合操作做准备。


void SurfaceFlinger::handlePageFlip()
{
//调用 lockPageFlip
visibleRegions |= lockPageFlip(currentLayers);

//取得屏幕的区域
const Region screenRegion(hw.bounds());
if (visibleRegions) {
   Region opaqueRegion;
   computeVisibleRegions(currentLayers, mDirtyRegion, opaqueRegion);
   .....
   mWormholeRegion = screenRegion.subtract(opaqueRegion);
}
.....
//调用 unlockPageFlip
unlockPageFlip(currentLayers);
}


上面的调用实际上是一对函数:lockPageFlip & lockPageFlip,那么主要干些啥呢?


bool SurfaceFlinger::lockPageFlip(const LayerVector& currentLayers)
{
    bool recomputeVisibleRegions = false;
    size_t count = currentLayers.size();
    sp<LayerBase> const* layers = currentLayers.array();


    //逐个 layer 进行处理 
    for (size_t i=0 ; i<count ; i++) {
        const sp<LayerBase>& layer(layers[i]);
        layer->lockPageFlip(recomputeVisibleRegions);
    }
    return recomputeVisibleRegions;
}


void Layer::lockPageFlip(bool& recomputeVisibleRegions)
{
SharedBufferServer* lcblk(sharedClient.get());

// 获取当前可用的 frontbuffer 索引号
ssize_t buf = lcblk->retireAndLock();

// 计算当前的脏区域
  sp<GraphicBuffer> newFrontBuffer(getBuffer(buf));
  if (newFrontBuffer != NULL) {
      // get the dirty region
      // compute the posted region
      const Region dirty(lcblk->getDirtyRegion(buf));
      mPostedDirtyRegion = dirty.intersect( newFrontBuffer->getBounds() );
      ....

// 如果有脏区域需要重绘,则生成 OpenGL ES 纹理贴图
reloadTexture( mPostedDirtyRegion );
}


void SurfaceFlinger::unlockPageFlip(const LayerVector& currentLayers)
{
    const GraphicPlane& plane(graphicPlane(0));
    const Transform& planeTransform(plane.transform());
    size_t count = currentLayers.size();
    sp<LayerBase> const* layers = currentLayers.array();
    for (size_t i=0 ; i<count ; i++) {
        const sp<LayerBase>& layer(layers[i]);


//进行区域的清理工作
        layer->unlockPageFlip(planeTransform, mDirtyRegion);
    }
}


void Layer::unlockPageFlip(
        const Transform& planeTransform, Region& outDirtyRegion)
{
    Region dirtyRegion(mPostedDirtyRegion);
    if (!dirtyRegion.isEmpty()) {
        mPostedDirtyRegion.clear();
....
    if (visibleRegionScreen.isEmpty()) {
        // an invisible layer should not hold a freeze-lock
        // (because it may never be updated and therefore never release it)
        mFreezeLock.clear();
    }
}


以上的工作就是按照 Zorder 序计算自已屏幕上的可显示区域:
1、以自己的W,H给出自己初始的可见区域
2、减去自己上面窗口所覆盖的区域






3、handleRepaint
每个Layer的数据都准备好了,并且各个脏区域也计算ok,下步就是根据 Zorder 序从底部将数据绘制到主Surface上


void SurfaceFlinger::handleRepaint()
{
    // compute the invalid region
    mInvalidRegion.orSelf(mDirtyRegion);


....


    // compose all surfaces
    composeSurfaces(mDirtyRegion);


    // clear the dirty regions
    mDirtyRegion.clear();
}


void SurfaceFlinger::composeSurfaces(const Region& dirty)
{
...
    const size_t count = layers.size();
    for (size_t i=0 ; i<count ; ++i) {
        const sp<LayerBase>& layer(layers[i]);
        const Region clip(dirty.intersect(layer->visibleRegionScreen));
        if (!clip.isEmpty()) {
            // 这就是绘图核心函数
            layer->draw(clip);
        }
    }
}



void Layer::onDraw(const Region& clip) const
---> drawWithOpenGL(clip, tex); 基本上都是OpenGL ES 操作函数


    while (it != end) {
        const Rect& r = *it++;
        const GLint sy = fbHeight - (r.top + r.height());
        // 裁剪
        glScissor(r.left, sy, r.width(), r.height());
        // 画矩形
        glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
    }

4、unlockClients()
释放 handlePageFlip 占用的 frontbuffer 索引号,以便客户端可以继续在新的surface画图


void SurfaceFlinger::unlockClients()
{
...
    for (size_t i=0 ; i<count ; ++i) {
        const sp<LayerBase>& layer = layers[i];
        layer->finishPageFlip();
    }
}


-->
SharedBufferServer* lcblk(sharedClient.get());
status_t err = lcblk->unlock( buf );



5、postFramebuffer()
现在已经将所有的Layer图层数据合成完成,最后就是输入到屏幕上显示了



void SurfaceFlinger::postFramebuffer()
{
//调用此函数将混合后的图像传递到屏幕中进行显示
hw.flip(mInvalidRegion);
...
}


void DisplayHardware::flip(const Region& dirty) const
{
// 显示图像吧。。。。。
    eglSwapBuffers(dpy, surface);

}


  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android 13 中,SurfaceFlinger线程扫描所有的 Surface 对象的代码要是由 `SurfaceFlinger::onMessageRefresh` 方法实现的。该方法是线程的消息处理函数,当线程收到“刷新”消息时,就会调用该方法。 具体来说,`SurfaceFlinger::onMessageRefresh` 方法的代码路径如下: 1. 遍历 SurfaceFlinger 中的所有 Layer(即 Surface 对象),并检查它们的状态是否发生了改变。这个过程是由线程中的 `mDrawingState.traverseInZOrder` 方法实现的,该方法会遍历所有的 Layer,并调用每个 Layer 的 `onPreComposition` 方法来检查它们的状态。 2. 如果某个 Layer 的状态发生了改变,就会调用相应的客户端进程,要求其重新提交该 Layer 的缓冲区。这个过程是由 `SurfaceFlinger::postComposition` 方法实现的,该方法会遍历所有的 Layer,并调用每个 Layer 的 `onPostComposition` 方法来通知客户端进程。 3. 如果客户端进程提交了新的缓冲区,就会将这些缓冲区合成到一个帧缓冲区中,并在下一次屏幕刷新时将其发送到显示器。这个过程是由线程中的 `composeSurfaces` 和 `drawWormhole` 方法实现的,它们会将所有的 Layer 缓冲区合成到一个帧缓冲区中,并在需要时添加虫洞(Wormhole)层用于处理透明度。 下面是 `SurfaceFlinger::onMessageRefresh` 方法的伪代码: ```cpp void SurfaceFlinger::onMessageRefresh() { // 遍历所有的 Layer,并检查它们的状态是否发生了改变 mDrawingState.traverseInZOrder([&](Layer* layer) { // 调用每个 Layer 的 onPreComposition 方法来检查它们的状态 layer->onPreComposition(); }); // 如果某个 Layer 的状态发生了改变,就通知客户端进程重新提交缓冲区 postComposition(); // 将所有的 Layer 缓冲区合成到一个帧缓冲区中,并添加虫洞层 composeSurfaces(); drawWormhole(); } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值