Android GUI系统之SurfaceFlinger(07)服务端分析2-handleMessageTransaction处理

该系列文章总纲链接:Android GUI系统之SurfaceFlinger 系列文章目录


本章关键点总结 & 说明:

本章节思维导图如上。主要讲述了SurfaceFlinger 处理Vsync机制的流程。主要分析handleMessageTransaction 处理方法。


继续上一节(Android GUI系统之SurfaceFlinger(06)服务端分析1-处理VSYNC)的分析,这里的INVALIDATE对应mQueue.mFlinger->onMessageReceived(message.what)方法的执行,onMessageReceived代码实现如下:

void SurfaceFlinger::onMessageReceived(int32_t what) {
    switch (what) {
        case MessageQueue::TRANSACTION: {
            handleMessageTransaction();
            break;
        }
        case MessageQueue::INVALIDATE: {
            //关键语句
            bool refreshNeeded = handleMessageTransaction();//1 
            refreshNeeded |= handleMessageInvalidate();//2 
            refreshNeeded |= mRepaintEverything;
            if (refreshNeeded) {
                signalRefresh();//3
            }
            break;
        }
        case MessageQueue::REFRESH: {
            handleMessageRefresh();
            break;
        }
    }
}

针对INVALIDATE消息,关键执行代码中标识的几句话。我们对其分别技能型详细的分析

handleMessageTransaction

handleMessageTransaction的代码实现如下:

bool SurfaceFlinger::handleMessageTransaction() {
    uint32_t transactionFlags = peekTransactionFlags(eTransactionMask);
    if (transactionFlags) {
        handleTransaction(transactionFlags);
        return true;
    }
    return false;
}

继续分析这里的handleTransaction,代码如下:

void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
{
    State drawingState(mDrawingState);
    Mutex::Autolock _l(mStateLock);
    const nsecs_t now = systemTime();
    mDebugInTransaction = now;
    //产生一个新的transactionFlags变量  
    transactionFlags = getTransactionFlags(eTransactionMask);
    handleTransactionLocked(transactionFlags);

    mLastTransactionTime = systemTime() - now;
    mDebugInTransaction = 0;
    invalidateHwcGeometry();
}

继续分析handleTransactionLocked,这也是本部分分析的重点,因为handleTransactionLocked的代码比较长,这类分成5个部分进行解读。

1 处理Layer的事务

抽取第一部分代码,实现如下:

void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
{
    const LayerVector& currentLayers(mCurrentState.layersSortedByZ);
    const size_t count = currentLayers.size();

    if (transactionFlags & eTraversalNeeded) {
        for (size_t i=0 ; i<count ; i++) {
            const sp<Layer>& layer(currentLayers[i]);
            uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded);
            if (!trFlags) continue;

            const uint32_t flags = layer->doTransaction(0);
            if (flags & Layer::eVisibleRegion)
                mVisibleRegionsDirty = true;
        }
    }
    //...
}

这里遍历每一个Layer,根据eTraversalNeeded标志来决定是否要检查Layer对象。如果Layer中有eTransactionNeeded标志,则返回非0值,然后调用它的doTransaction函数。Layer的doTransaction函数返回的flags如果有eVisibleRegion,则说明该Layer需要更新,mVisibleRegionsDirty设置为true。这里继续分析Layer的doTransaction函数,代码如下:

uint32_t Layer::doTransaction(uint32_t flags) {
    const Layer::State& s(getDrawingState());//上次绘制使用的State对象  
    const Layer::State& c(getCurrentState());//当前绘制使用的State对象  

    const bool sizeChanged = (c.requested.w != s.requested.w) ||
                             (c.requested.h != s.requested.h);
    //如果两个对象的大小不相等,说明Layer的尺寸发生变化  
    if (sizeChanged) {
        mSurfaceFlingerConsumer->setDefaultBufferSize(
                c.requested.w, c.requested.h);
    }

    if (!isFixedSize()) {
        const bool resizePending = (c.requested.w != c.active.w) ||
                                   (c.requested.h != c.active.h);
        //如果两者不一样,flags加上不更新Geometry标志
        if (resizePending) {
            flags |= eDontUpdateGeometryState;
        }
    }

    if (flags & eDontUpdateGeometryState)  {
    } else {
        //如果没有eDontUpdateGeometryState标志,更新active的值为request
        Layer::State& editCurrentState(getCurrentState());
        editCurrentState.active = c.requested;
    }

    if (s.active != c.active) {
        // 如果当前state的active和以前的State的active不等,设置更新标志  
        flags |= Layer::eVisibleRegion;
    }

    if (c.sequence != s.sequence) {
        //如果当前state的sequence和以前state的sequence不等,设置更新标志 
        flags |= eVisibleRegion;
        this->contentDirty = true;

        // we may use linear filtering, if the matrix scales us
        const uint8_t type = c.transform.getType();
        mNeedsFiltering = (!c.transform.preserveRects() ||
                (type >= Transform::SCALE));
    }

    //将mCurrentState的值赋给mDrawingState
    commitTransaction();
    return flags;
}

这里留意:Layer类中的两个类型为Layer::State的成员变量mDrawingState、mCurrentState,Layer::State类型代码如下:

struct State {  
    Geometry active;	//实际大小  
    Geometry requested;	//用户大小  
    uint32_t z;			//Z轴值  
    uint32_t layerStack;//和显示设备的关联值  
    uint8_t alpha;
    uint8_t flags; 
    uint8_t reserved[2];  
    int32_t sequence; 	//序列值,Layer的属性变化一次,这个值就加1  
    Transform transform;
    Region activeTransparentRegion;//实际的透明区域  
    Region requestedTransparentRegion;//用户层的透明区域  
};

Layer对象在绘制图形时,使用的是mDrawingState变量,用户调用接口设置Layer对象属性是,设置的值保存在mCurrentState对象中,这样就不会因为用户的操作而干扰Layer对象的绘制了。所以这里有两个对象。

接下来对State 结构体中的一些变量进行说明:

  1. Geometry字段:State的结构中有两个Geometry字段,active和requested。他们表示layer的尺寸,其中requested保存是用户设置的尺寸,而active保存的值通过计算后的实际尺寸。
  2. layerStack字段:它是用户指定的一个值,用户可以给DisplayDevice也指定一个layerStack值,只有Layer对象和DisplayDevice对象的layerStack相等,这个Layer才能在这个显示设备上输出,这样的好处是可以让显示设备只显示某个Surface的内容。例如,可以让HDMI显示设备只显示手机上播放视频的Surface窗口,但不显示Activity窗口。
  3. sequence字段:它是一个序列值,每当用户调用了Layer的接口,例如setAlpha、setSize或者setLayer等改变Layer对象属性的哈数,这个值都会加1。因此在doTransaction函数中能通过比较sequence值来判断Layer的属性值有没有变化。

可以看到Layer::State中的layerStack中会对比DisplayDeviceState对象的layerStack,所以分析下DisplayDeviceState,代码如下:

    struct DisplayDeviceState {
        DisplayDeviceState();
        DisplayDeviceState(DisplayDevice::DisplayType type);
        bool isValid() const { return type >= 0; }
        bool isMainDisplay() const { return type == DisplayDevice::DISPLAY_PRIMARY; }
        bool isVirtualDisplay() const { return type >= DisplayDevice::DISPLAY_VIRTUAL; }
        DisplayDevice::DisplayType type;
        sp<IGraphicBufferProducer> surface;
        uint32_t layerStack;//关键点
        Rect viewport;
        Rect frame;
        uint8_t orientation;
        uint32_t width, height;
        String8 displayName;
        bool isSecure;
    };

可以说这里的layerStack和Layer的State中的layerStack如果相等,则Layer可以在该State对应的DisplayDevice中显示。

2 处理显示设备的变化

抽取第二部分代码,实现如下:

    //...
    if (transactionFlags & eDisplayTransactionNeeded) {
        //得到当前显示设备列表和之前使用的显示设备列表
        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();//以前显示设备的数量

            for (size_t i=0 ; i<dc ; i++) {
                const ssize_t j = curr.indexOfKey(draw.keyAt(i));
                if (j < 0) {//设备被删除
                    // in drawing state but not in current state
                    if (!draw[i].isMainDisplay()) {
                        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 {
                        ALOGW("trying to remove the main display");
                    }
                } else {设备还在,再检查有没有其他变化
                    // this display is in both lists. see if something changed.
                    const DisplayDeviceState& state(curr[j]);
                    const wp<IBinder>& display(curr.keyAt(j));
                    if (state.surface->asBinder() != draw[i].surface->asBinder()) {
                        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) {
                        //两个对象layerStack不等,使用当前对象的  
                        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);
                        }
                    }
                }
            }
            //处理显示设备增加的情况。。。
        }
    }
    //...

这段代码主要是处理显示设备的变化:

  1. 移除不需要的显示设备,将其对应的DisplayDevice移除
  2. 对于发生变化的显示设备(设置Surface、重置layerStack、旋转。。。),就需要重置显示对象的属性
  3. 对于新增加的显示设备,创建DisplayDevice并加入到系统

3 设置TransfromHit

抽取第三部分代码,实现如下:

    //...
    if (transactionFlags & (eTraversalNeeded|eDisplayTransactionNeeded)) {
        sp<const DisplayDevice> disp;
        uint32_t currentlayerStack = 0;
        for (size_t i=0; i<count; i++) {
            const sp<Layer>& layer(currentLayers[i]);
            uint32_t layerStack = layer->getDrawingState().layerStack;
            if (i==0 || currentlayerStack != layerStack) {
                currentlayerStack = layerStack;
                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对象的TransformHint
            layer->updateTransformHint(disp);
        }
    }
    //...

这段代码根据每种显示设备的不同,设置和显示设备关联在一起的Layer(主要看Layer的layerStack是否和DisplayDevice的layerStack一致)的TransformHint(主要指设备的显示方向orientation)

4 处理Layer增减情况

抽取第四部分代码,实现如下:

    //...
    const LayerVector& layers(mDrawingState.layersSortedByZ);
    if (currentLayers.size() > layers.size()) {
        //如果有Layer加入,设置需要更新 
        mVisibleRegionsDirty = true;
    }

    if (mLayersRemoved) {//有Layer删除
        mLayersRemoved = false;
        mVisibleRegionsDirty = true;
        const size_t count = layers.size();
        for (size_t i=0 ; i<count ; i++) {
            const sp<Layer>& layer(layers[i]);
            //如果这个Layer不存在,则把它的所在区域设置为需要更新的区域
            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);
            }
        }
    }
    //...

这段代码处理Layer的增减情况:

  1. 如果有Layer增加,需要重新计算设备的更新区域,mVisibleRegionsDirty设置为true
  2. 如果有Layer被删除,需要把Layer的可见区域加入到系统需要更新的区域中

5 设置mDrawingState

抽取第五部分代码,实现如下:

    //...
    commitTransaction();
    updateCursorAsync();
}

分别对commitTransaction和updateCursorAsync进行简单的分析。

5.1 commitTransaction

代码实现如下:

void SurfaceFlinger::commitTransaction()
{
    if (!mLayersPendingRemoval.isEmpty()) {
        // Notify removed layers now that they can't be drawn from
        for (size_t i = 0; i < mLayersPendingRemoval.size(); i++) {
            mLayersPendingRemoval[i]->onRemoved();
        }
        mLayersPendingRemoval.clear();
    }

    mAnimCompositionPending = mAnimTransactionPending;

    mDrawingState = mCurrentState;//关键点
    mTransactionPending = false;
    mAnimTransactionPending = false;
    mTransactionCV.broadcast();
}

commitTransaction函数最关键的作用是把mDrawingState的值设置成mCurrentState的值。

5.2 updateCursorAsync

代码实现如下:

void SurfaceFlinger::updateCursorAsync()
{
    HWComposer& hwc(getHwComposer());
    for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
        sp<const DisplayDevice> hw(mDisplays[dpy]);
        const int32_t id = hw->getHwcDisplayId();
        if (id < 0) {
            continue;
        }
        const Vector< sp<Layer> >& currentLayers(
            hw->getVisibleLayersSortedByZ());
        const size_t count = currentLayers.size();
        HWComposer::LayerListIterator cur = hwc.begin(id);
        const HWComposer::LayerListIterator end = hwc.end(id);
        for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) {
            if (cur->getCompositionType() != HWC_CURSOR_OVERLAY) {
                continue;
            }
            const sp<Layer>& layer(currentLayers[i]);
            Rect cursorPos = layer->getPosition(hw);
            hwc.setCursorPositionAsync(id, cursorPos);
            break;
        }
    }
}

updateCursorAsync函数会更新所有显示设备中光标的位置。

6 总结

该部分代码主要是处理事物:

  1. 遍历每一个Layer,根据条件执行对应的doTransaction,根据返回值设置mVisibleRegionsDirty
  2. 处理显示设备的变化:增加/删除/变化
  3. 对Layer的TransfromHit(旋转角度)进行设置
  4. 处理SurfaceFlinger本身的事物:Layer的增减情况

总结下,虽然处理了很多事物,但主要是设置一些flag,但并未对相关的Buffer进行实际的操作。handleTransaction函数的作用的就是处理系统在两次刷新期间的各种变化。SurfaceFlinger模块 中不管是SurfaceFlinger类还是Layer类,都采用了双缓冲的方式来保存他们的属性,这样的好处是刚改变SurfaceFlinger对象或者Layer类对象的属性时不需要上锁,这很大程度上提高了系统效率。只有在最后的图像输出才会进行一次上锁,并将内存的属性变化进行处理。正因此,应用进程必须收到VSync信号才开始改变Surface中Buffer的内容。

 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

图王大胜

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值