美文网首页
SurfaceFlinger图像合成[1]

SurfaceFlinger图像合成[1]

作者: 泡面先生_Jack | 来源:发表于2020-01-11 15:05 被阅读0次

    Layer接收到新的GraphicBuffer

    void Layer::onFrameAvailable(const BufferItem& item) {
        // 将新的Buffer添加到Layer内部的mQueueItems队列进行处理
        { 
            ....
            //将 BufferItem放入Layer队列中
            mQueueItems.push_back(item);
            //Layer中待处理Buffer +1
            android_atomic_inc(&mQueuedFrames);
    
            // Wake up any pending callbacks
            mLastFrameNumberReceived = item.mFrameNumber;
            ....
        }
       //通知SurfaceFlinger进行更新
        mFlinger->signalLayerUpdate();
    }
    

    Layer中接收到其生产者产生的GraphicBuffer后会接收到onFrameAvailable的通知,Layer将新的Buffer信息放入自己的mQueueItems队列中等待合成,待合成的Buffer数量+1,最后调用signalLayerUpdate通知SurfaceFlinger合成.

    void SurfaceFlinger::signalLayerUpdate() {
        mEventQueue.invalidate();
    }
    
    void MessageQueue::invalidate() {
        ......
        mEvents->requestNextVsync();
        ......
    }
    

    signalLayerUpdate方法调用了MessageQueue的invalidate方法,而invalidate又调用了requestNextVsync方法,这个方法在Vsync分析的时候已经了解过,主要作用是通知Vsync机制在下一次SF的Vsync到来的时候唤醒SF进行工作. 而SF在接收到下次Vsync到来的时候便会执行图形合成.
    再来看下SF接收到Vsync的处理流程

    void SurfaceFlinger::onMessageReceived(int32_t what) {
        ATRACE_CALL();
        switch (what) {
            ......
            //Vsync到来执行invalidate方法
            case MessageQueue::INVALIDATE: {
                bool refreshNeeded = handleMessageTransaction();
                refreshNeeded |= handleMessageInvalidate();
                refreshNeeded |= mRepaintEverything;
                if (refreshNeeded) {
                    // 更加更新结果决定是否需要进行刷新屏幕显示,如果窗口状态发生了变化,则需要重新合成并刷新屏幕显示.
                    signalRefresh();
                }
                break;
            }
            //合成UI刷新到屏幕
            case MessageQueue::REFRESH: {
                handleMessageRefresh();
                break;
            }
        }
    }
    
    

    SF图形合成又大体上分为了两个部分
    1:SF更新合成相关的信息
    2:SF执行合成操作并显示

    SF根据更新结果来决定是否需要再次合成并显示,

    SF更新合成相关的信息

    handleMessageTransaction

    handleMessageTransaction主要处理Layer属性变化, 显示设备变化等情况,最终将变化的信息mCurrentState提交到mDrawingState, 等待合成处理.

    handleMessageTransaction方法经过层层调用最终执行到 handleTransactionLocked方法中,我们直接看这个方法.
    SF有两个状态 mDrawingState表示正在绘制显示的状态,mCurrentState表示从上次 绘制后 发生变化的信息. 修改的信息都保存在mCurrentState中,等到修改完成后统一提交到mDrawingState中。

    void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
    {
        //获取mCurrentState中所有的Layer。
        const LayerVector& currentLayers(mCurrentState.layersSortedByZ);
        const size_t count = currentLayers.size();
    
        //遍历mCurrentState中所有的Layer,对发生变化的Layer执行doTransaction函数,判断Layer的可见区域是否发生了变化
        if (transactionFlags & eTraversalNeeded) {
            for (size_t i=0 ; i<count ; i++) {
                const sp<Layer>& layer(currentLayers[i]);
                //根据eTransactionNeeded,判断Layer是否发生了变化,Layer发生变化后会设置这个flag
                uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded);
                if (!trFlags) continue;
    
                //Layer的doTransaction函数会会对比Layer的旧的状态和新的状态是否发生变化,当Layer的可见区域大小发生变化之后,设置mVisibleRegionsDirty为true
                const uint32_t flags = layer->doTransaction(0);
                if (flags & Layer::eVisibleRegion)
                    mVisibleRegionsDirty = true;
            }
        }
    

    handleTransactionLocked第一部分:检查Layer VisibleRegion是否发生变化.
    遍历所有的Layer查看SF的visibleRegion是否发生了变化,首先会先检查Layer是否发生了变化, Layer没有发生变化则不需要检查该Layer,如果Layer发生了变化,需要对比该Layer的显示区域和原来显示区域是否发生变化,若变化设置mVisibleRegionsDirty为true。

        //遍历并检查所有的显示设备,检查显示设备是否发生了增加或者减少.并做相应的处理
        if (transactionFlags & eDisplayTransactionNeeded) {
            //两个列表来保存上次合成时显示设备的信息和当前显示设备的信息
            // draw 上次合成时显示设备信息
            // curr 当前显示设备的信息
            const KeyedVector<  wp<IBinder>, DisplayDeviceState>& curr(mCurrentState.displays);
            const KeyedVector<  wp<IBinder>, DisplayDeviceState>& draw(mDrawingState.displays);
            //判断是否发生变化
            if (!curr.isIdenticalTo(draw)) {
                mVisibleRegionsDirty = true;
                const size_t cc = curr.size();
                      size_t dc = draw.size();
    
                // 找到删除的显示设备信息
                // (ie: 在draw列表中,但是却不在curr列表中,说明有设备删除)
                // 处理显示设备发生变化
                // (ie: 两个列表中都有该显示设备)
                for (size_t i=0 ; i<dc ; i++) {
                    const ssize_t j = curr.indexOfKey(draw.keyAt(i));
                    if (j < 0) {
                        // 1: 显示设备移除: 在draw列表中,却不在curr列表中
                        if (!draw[i].isMainDisplay()) {
                            // 如果有设备移除,切当前设备不是主显示设备的时候,将EGL的Context设置到默认的主显示设备
                            // 从HWC断开该设备,通知EventThread设备热插拔事件,从Display列表移除
                            const sp<const DisplayDevice> defaultDisplay(getDefaultDisplayDevice());
                            defaultDisplay->makeCurrent(mEGLDisplay, mEGLContext);
                            sp<DisplayDevice> hw(getDisplayDevice(draw.keyAt(i)));
                            if (hw != NULL)
                                hw->disconnect(getHwComposer());
                            if (draw[i].type < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES)
                                mEventThread->onHotplugReceived(draw[i].type, false);
                            mDisplays.removeItem(draw.keyAt(i));
                        } else {
                            // 主设备不允许移除,打印Warnning 提示信息
                            ALOGW("trying to remove the main display");
                        }
                    } else {
                        // 设备在两个列表中都有,但是有信息发生了变化
                        const DisplayDeviceState& state(curr[j]);
                        const wp<IBinder>& display(curr.keyAt(j));
                        const sp<IBinder> state_binder = IInterface::asBinder(state.surface);
                        const sp<IBinder> draw_binder = IInterface::asBinder(draw[i].surface);
                        if (state_binder != draw_binder) {
                            // changing the surface is like destroying and
                            // recreating the DisplayDevice, so we just remove it
                            // from the drawing state, so that it get re-added
                            // below.
                            sp<DisplayDevice> hw(getDisplayDevice(display));
                            if (hw != NULL)
                                hw->disconnect(getHwComposer());
                            mDisplays.removeItem(display);
                            mDrawingState.displays.removeItemsAt(i);
                            dc--; i--;
                            // at this point we must loop to the next item
                            continue;
                        }
                        //更新显示设备信息
                        const sp<DisplayDevice> disp(getDisplayDevice(display));
                        if (disp != NULL) {
                            if (state.layerStack != draw[i].layerStack) {
                                disp->setLayerStack(state.layerStack);
                            }
                            if ((state.orientation != draw[i].orientation)
                                    || (state.viewport != draw[i].viewport)
                                    || (state.frame != draw[i].frame))
                            {
                                disp->setProjection(state.orientation,
                                        state.viewport, state.frame);
                            }
                            if (state.width != draw[i].width || state.height != draw[i].height) {
                                disp->setDisplaySize(state.width, state.height);
                            }
                        }
                    }
                }
    
                // 找到新添加的Display设备信息
                // (ie: draw列表中没有,curr列表中有该设备,说明有新设备添加进来)
                for (size_t i=0 ; i<cc ; i++) {
                    if (draw.indexOfKey(curr.keyAt(i)) < 0) {
                        const DisplayDeviceState& state(curr[i]);
    
                        sp<DisplaySurface> dispSurface;
                        sp<IGraphicBufferProducer> producer;
                        sp<IGraphicBufferProducer> bqProducer;
                        sp<IGraphicBufferConsumer> bqConsumer;
                        BufferQueue::createBufferQueue(&bqProducer, &bqConsumer,
                                new GraphicBufferAlloc());
    
                        int32_t hwcDisplayId = -1;
                        if (state.isVirtualDisplay()) {
                            // 虚拟显示设备暂时不关注
                            if (state.surface != NULL) {
    
                                int width = 0;
                                int status = state.surface->query(
                                        NATIVE_WINDOW_WIDTH, &width);
                                ALOGE_IF(status != NO_ERROR,
                                        "Unable to query width (%d)", status);
                                int height = 0;
                                status = state.surface->query(
                                        NATIVE_WINDOW_HEIGHT, &height);
                                ALOGE_IF(status != NO_ERROR,
                                        "Unable to query height (%d)", status);
                                if (MAX_VIRTUAL_DISPLAY_DIMENSION == 0 ||
                                        (width <= MAX_VIRTUAL_DISPLAY_DIMENSION &&
                                         height <= MAX_VIRTUAL_DISPLAY_DIMENSION)) {
                                    hwcDisplayId = allocateHwcDisplayId(state.type);
                                }
    
                                sp<VirtualDisplaySurface> vds = new VirtualDisplaySurface(
                                        *mHwc, hwcDisplayId, state.surface,
                                        bqProducer, bqConsumer, state.displayName);
    
                                dispSurface = vds;
                                producer = vds;
                            }
                        } else {
                            //为新添加的设备分配HWC ID,并创建FramebufferSurface消费者.
                            ALOGE_IF(state.surface!=NULL,
                                    "adding a supported display, but rendering "
                                    "surface is provided (%p), ignoring it",
                                    state.surface.get());
                            hwcDisplayId = allocateHwcDisplayId(state.type);
                            dispSurface = new FramebufferSurface(*mHwc, state.type,
                                    bqConsumer);
                            producer = bqProducer;
                        }
    
                        const wp<IBinder>& display(curr.keyAt(i));
                        if (dispSurface != NULL) {
                            //创建该显示设备的DisplayDevice,并添加到mDisplays中.
                            sp<DisplayDevice> hw = new DisplayDevice(this,
                                    state.type, hwcDisplayId,
                                    mHwc->getFormat(hwcDisplayId), state.isSecure,
                                    display, dispSurface, producer,
                                    mRenderEngine->getEGLConfig());
                            hw->setLayerStack(state.layerStack);
                            hw->setProjection(state.orientation,
                                    state.viewport, state.frame);
                            hw->setDisplayName(state.displayName);
                            mDisplays.add(display, hw);
                            if (state.isVirtualDisplay()) {
                                if (hwcDisplayId >= 0) {
                                    mHwc->setVirtualDisplayProperties(hwcDisplayId,
                                            hw->getWidth(), hw->getHeight(),
                                            hw->getFormat());
                                }
                            } else {
                                // 通知EventThread有新设备热插拔
                                mEventThread->onHotplugReceived(state.type, true);
                            }
                        }
                    }
                }
            }
        }
    

    handleTransactionLocked第二部分:检查显示设备是否发生变化
    1:检查Display是否移除,则更新SF移除相关的信息
    2:检查Display是否发生变化, 若发生变化则需要将Display相关的信息更新为新的显示设备信息
    3:检查Display是否添加新设备,若添加新设备,则按照设备添加流程为新设备创建BufferQueue和FrameBufferSurface等.

        //当显示设备发生变化或者某些Layer发生变化后,需要修改Layer的transform hint, 使Layer视图的矩阵变化。
        //遍历mCurrentState所有的Layer并更新他的transform hint
        //如果一个Layer只显示在一个显示设备上,那我们就用这个显示设备来计算他的Transform hint,如果显示在多个显示设备上,则需要按照默认主显示设备计算.
        if (transactionFlags & (eTraversalNeeded|eDisplayTransactionNeeded)) {
            
            sp<const DisplayDevice> disp;
            uint32_t currentlayerStack = 0;
            for (size_t i=0; i<count; i++) {
                // NOTE: we rely on the fact that layers are sorted by
                // layerStack first (so we don't have to traverse the list
                // of displays for every layer).
                const sp<Layer>& layer(currentLayers[i]);
                uint32_t layerStack = layer->getDrawingState().layerStack;
                if (i==0 || currentlayerStack != layerStack) {
                    currentlayerStack = layerStack;
                    //根据当前Layer的layerStack找到所属的显示设备Display
                    disp.clear();
                    for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
                        sp<const DisplayDevice> hw(mDisplays[dpy]);
                        if (hw->getLayerStack() == currentlayerStack) {
                            if (disp == NULL) {
                                disp = hw;
                            } else {
                                disp = NULL;
                                break;
                            }
                        }
                    }
                }
                if (disp == NULL) {
                    //如果显示在过个显示设备上,则使用默认显示设备
                    disp = getDefaultDisplayDevice();
                }
                //将显示设备信息更新到Layer中
                layer->updateTransformHint(disp);
            }
        }
    
    

    handleTransactionLocked第三部分:更新transform hint相关信息
    当显示设备发生变化或者某些Layer发生变化后,需要修改Layer的transform hint.

        
        //如有有新添加的Layer, 则mVisibleRegionsDirty = true
        const LayerVector& layers(mDrawingState.layersSortedByZ);
        if (currentLayers.size() > layers.size()) {
            // layers have been added
            mVisibleRegionsDirty = true;
        }
    
        // 如果有Layer移除, 该Layer原先的显示区域就是需要更新显示区域
        if (mLayersRemoved) {
            mLayersRemoved = false;
            mVisibleRegionsDirty = true;
            const size_t count = layers.size();
            for (size_t i=0 ; i<count ; i++) {
                const sp<Layer>& layer(layers[i]);
                if (currentLayers.indexOf(layer) < 0) {
                    const Layer::State& s(layer->getDrawingState());
                    Region visibleReg = s.transform.transform(
                            Region(Rect(s.active.w, s.active.h)));
                    invalidateLayerStack(s.layerStack, visibleReg);
                }
            }
        }
    
        commitTransaction();
    
    }
    

    handleTransactionLocked第四部分: 更新Layer信息
    若有Layer移除,更新SF的visibleRegion, 说明原来该Layer显示的区域需要重新刷新显示
    最后调用commitTransaction,提交mCurrentState信息, 将所有变化的信息更新完成后,mCurrentState提交到mDrawingState中. 下一步就要合成显示这些变化后的内容了.

    handleMessageInvalidate

    handleMessageInvalidate会调用handlePageFlip函数. 直接看handlePageFlip的逻辑

    handlePageFlip

    bool SurfaceFlinger::handlePageFlip()
    {
        Region dirtyRegion;
    
        bool visibleRegions = false;
        //拿到mDrawingState中的所有Layer, 就是我们上一步中刚提交的变化的Layer
        const LayerVector& layers(mDrawingState.layersSortedByZ);
        bool frameQueued = false;
    
        //遍历所有的Layer, 找到有新的Buffer到来需要合成的Layer,将这些Layer添加到layersWithQueuedFrames列表中.
        //那些Layer需要合成呢?
        // 1:Layer中有新的待处理的Buffer
        // 2:Buffer需要立刻显示的。(未到指定显示时间的不需要处理)
        Vector<Layer*> layersWithQueuedFrames;
        for (size_t i = 0, count = layers.size(); i<count ; i++) {
            const sp<Layer>& layer(layers[i]);
            if (layer->hasQueuedFrame()) {
                frameQueued = true;
                if (layer->shouldPresentNow(mPrimaryDispSync)) {
                    layersWithQueuedFrames.push_back(layer.get());
                } else {
                    layer->useEmptyDamage();
                }
            } else {
                layer->useEmptyDamage();
            }
        }
        //遍历所有需要处理的Layer,并从BufferQueue中获取Buffer并更新,最终更新到Display的visibleRegion中
        for (size_t i = 0, count = layersWithQueuedFrames.size() ; i<count ; i++) {
            Layer* layer = layersWithQueuedFrames[i];
            //latchBuffer是在BufferQueue中分析过,从BufferQueue中获取Buffer,并将Buffer绑定到Layer对应的纹理上.
            const Region dirty(layer->latchBuffer(visibleRegions));
            layer->useSurfaceDamage();
            const Layer::State& s(layer->getDrawingState());
            //将Layer的visibleRegion 更新到对应显示设备的Display上.
            invalidateLayerStack(s.layerStack, dirty);
        }
    
        mVisibleRegionsDirty |= visibleRegions;
    
        // Layer有待处理的Buffer,但是不到显示时间,则设置下一个Vsync到来的时候唤醒SF进行处理.
        if (frameQueued && layersWithQueuedFrames.empty()) {
            signalLayerUpdate();
        }
    
        // 如果有需要处理的Layer, layersWithQueuedFrames中有数据,则需要刷新合成
        return !layersWithQueuedFrames.empty();
    }
    

    handlePageFlip方法主要来处理Layer Buffer相关的内容.
    1: 找到此次Vsync事件中有需要处理的Buffer的Layer。
    2: 遍历所有需要待处理的Layer, 从BufferQueue中拿出该Layer对应的Buffer,更新到Layer对应的纹理中, 计算Layer的visible区域,更新到对应显示设备的DisplayDevice上。
    3: 判断Layer是否有待处理但是还没有到指定事件的Buffer, 如果有则需要下次Vsync事件在处理,调用signalLayerUpdate预约下次Vsync事件.
    4: 返回结果:如果此次Vsync有要处理的Layer,则说明需要重新合成,返回结果为true。

    总结

    此时invalidate就基本就分析完了.总结下

        bool refreshNeeded = handleMessageTransaction();
        refreshNeeded |= handleMessageInvalidate();
        refreshNeeded |= mRepaintEverything;
        if (refreshNeeded) {
            // Signal a refresh if a transaction modified the window state,
            // a new buffer was latched, or if HWC has requested a full
            // repaint
            signalRefresh();
        }
    

    Vsync到来时,INVALIDATE过程主要处理了 SF中距上次合成后的一些变化信息。
    1:handleMessageTransaction 处理了Layer属性变化, 显示设备变化等情况,然后将变化的信息mCurrentState提交到了mDrawingState,等待合成处理.
    主要包括Layer属性发生变化,显示设备添加和移除的处理,更新显示设备的transform hint相关的信息,处理Layer移除和增加等相关的信息,如果这些信息发生变化, 则需要重新合成刷新显示。
    2:handleMessageInvalidate 更新了Layer的buffer内容到Layer的纹理
    找到有待处理Buffer的Layer, 将Layer的buffer从BufferQueue中拿到,更新到纹理中. 如果内容发生变化,需要重新刷新合成.
    3:mRepaintEverything 表示HWC硬件要求强制刷新

    当以上过程中有对应的条件发生了变化,就会调用signalRefresh,通知SF进行合成刷新.

    相关文章

      网友评论

          本文标题:SurfaceFlinger图像合成[1]

          本文链接:https://www.haomeiwen.com/subject/snomoctx.html