Android6.0 图像合成过程详解(一) setUpHWComposer函数

上一篇博客分析了,用户进程如何申请一个GraphicBuffer的过程。这篇博客我们进一步分析图像合成过程,其中也解答之前的一些疑惑:

1. 之前碰到的不支持硬件模块

2. DisplayDevice类

3. 消费者的onFrameAvailable函数

我们直接分析合成的过程,具体的流程我们http://blog.csdn.net/kc58236582/article/details/52778333这篇博客分析了,这篇博客我们增加了一些以前没理解的点。


一、handleTransactionLocked函数

1.1 Layer的doTransaction函数

这里我直接从handleTransactionLocked函数开始分析,这个函数先会调用每个Layer对象的doTransaction函数,我们先来看看这个函数。

uint32_t Layer::doTransaction(uint32_t flags) {
    ATRACE_CALL();

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

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

    if (sizeChanged) {//如果Layer的尺寸发生变化,就要改变Surface的缓冲区的尺寸
        mSurfaceFlingerConsumer->setDefaultBufferSize(
                c.requested.w, c.requested.h);
    }

    if (!isFixedSize()) {
        //如果Layer不是固定尺寸的类型,比较它的实际大小和要求的改变大小
        const bool resizePending = (c.requested.w != c.active.w) ||
                                   (c.requested.h != c.active.h);

        if (resizePending && mSidebandStream == NULL) {//如果两者不一样,flags加上不更新Geometry标志
            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;

        const uint8_t type = c.transform.getType();
        mNeedsFiltering = (!c.transform.preserveRects() ||
                (type >= Transform::SCALE));
    }

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

这个函数之前博客也分析过,这里我们看看其中最重要的一个flag就是eVisibleRegion代表这个Layer是否要更新。而这里如果要更新Layer,也只是大小,sequence(也就是属性)变化才会更新这个flag。而Layer内容(buffer)的更新不在这里。这里使用了mDrawingState,mCurrentState两个变量。这两个变量主要是一些属性值。

最后会把mCurrentState的值赋给mDrawingState。而mCurrentState是在下面一些函数中变化的:

bool Layer::setPosition(float x, float y) {
    if (mCurrentState.transform.tx() == x && mCurrentState.transform.ty() == y)
        return false;
    mCurrentState.sequence++;
    mCurrentState.transform.set(x, y);
    setTransactionFlags(eTransactionNeeded);
    return true;
}
bool Layer::setLayer(uint32_t z) {
    if (mCurrentState.z == z)
        return false;
    mCurrentState.sequence++;
    mCurrentState.z = z;
    setTransactionFlags(eTransactionNeeded);
    return true;
}
bool Layer::setSize(uint32_t w, uint32_t h) {
    if (mCurrentState.requested.w == w && mCurrentState.requested.h == h)
        return false;
    mCurrentState.requested.w = w;
    mCurrentState.requested.h = h;
    setTransactionFlags(eTransactionNeeded);
    return true;
}
bool Layer::setAlpha(uint8_t alpha) {
    if (mCurrentState.alpha == alpha)
        return false;
    mCurrentState.sequence++;
    mCurrentState.alpha = alpha;
    setTransactionFlags(eTransactionNeeded);
    return true;
}

我们下面开始看handleTransactionLocked函数。

先看下处理layer的事务,遍历每个Layer的doTransaction来更新状态,以及根据flags是否要更新layer。

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

    /*
     * Traversal of the children
     * (perform the transaction for each of them if needed)
     */

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

            const uint32_t flags = layer->doTransaction(0);//遍历每个layer,更新mDrawingState状态
            if (flags & Layer::eVisibleRegion)
                mVisibleRegionsDirty = true;//有需要更新的layer,把该变量置为true
        }
    }

1.2 处理显示设备的变化

下面是handleTransactionLocked中处理显示设备的变化的

    if (transactionFlags & eDisplayTransactionNeeded) {
        //得到当前显示设备列表和之前使用的显示设备列表
        const KeyedVector<  wp, DisplayDeviceState>& curr(mCurrentState.displays);
        const KeyedVector<  wp, 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 ; i0代表这个设备两个列表中都存在,再检查有没有其他变化
                    // this display is in both lists. see if something changed.
                    const DisplayDeviceState& state(curr[j]);
                    const wp& display(curr.keyAt(j));
                    const sp state_binder = IInterface::asBinder(state.surface);
                    const sp draw_binder = IInterface::asBinder(draw[i].surface);
                    if (state_binder != draw_binder) {
                        //设备的Surface已经发生了变化(Surface对象不是一个了),旧的设备必须先删除掉
                        sp 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 disp(getDisplayDevice(display));
                    if (disp != NULL) {
                        //两个对象的layerStack不相等,使用当前对象的
                        if (state.layerStack != draw[i].layerStack) {
                            disp->setLayerStack(state.layerStack);
                        }
                        //如果两个对象的方向、viewport、frame不相等,使用当前对象的
                        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);
                        }
                    }
                }
            }

            // 处理显示设备增加的情况
            for (size_t i=0 ; i& display(curr.keyAt(i));
                    if (dispSurface != NULL) {
                        sp hw = new DisplayDevice(this,
                                state.type, hwcDisplayId,
                                mHwc->getFormat(hwcDisplayId), state.isSecure,
                                display, dispSurface, producer,
                                mRenderEngine->getEGLConfig());
                        ......
                        mDisplays.add(display, hw);
                        ......
                    }
                }
            }
        }
    }

这段代码的作用是处理显示设备的变化,分成3种情况:

1.显示设备减少了,需要把显示设备对应的DisplayDevice移除

2.显示设备发生了变化,例如用户设置了Surface、重新设置了layerStack、旋转了屏幕等,这就需要重新设置显示对象的属性

3.显示设备增加了,创建新的DisplayDevice加入系统中。

这些在之前博客都分析过,我们主要看下几个变量mCurrentState.displays, mDrawingState.displays。代表之前的设备和现在的设备。

这些displays是State的一个变量,是每个display的一个唯一码对应一个DisplayDeviceState(状态)。

    struct State {
        LayerVector layersSortedByZ;
        DefaultKeyedVector< wp, DisplayDeviceState> displays;
    };

而mDisplays是一个Display的唯一码 对应一个DisplayDevice。

    DefaultKeyedVector< wp, sp > mDisplays;

而这里主要用mCurrentState.displays, mDrawingState.displays中的Display的唯一码看哪个DisplayDevice增加了或者删除了,再去根据这个唯一码来对应在mDisplays中的DisplayDevice增加或者删除或者一些状态的修改。


1.3 设置TransformHint

    if (transactionFlags & (eTraversalNeeded|eDisplayTransactionNeeded)) {
        sp disp;
        uint32_t currentlayerStack = 0;
        for (size_t i=0; i& layer(currentLayers[i]);
            uint32_t layerStack = layer->getDrawingState().layerStack;
            if (i==0 || currentlayerStack != layerStack) {
                currentlayerStack = layerStack;
                // figure out if this layerstack is mirrored
                // (more than one display) if so, pick the default display,
                // if not, pick the only display it's on.
                disp.clear();//清除disp
                for (size_t dpy=0 ; dpy hw(mDisplays[dpy]);
                    if (hw->getLayerStack() == currentlayerStack) {
                        if (disp == NULL) {
                            disp = hw;//找到了一个layerStacker相同的显示设备
                        } else {
                            disp = NULL;//如果有两个显示设备的layerStacker相同,都不用
                            break;
                        }
                    }
                }
            }
            if (disp == NULL) {
                // 没有找到具有相同layerStack的显示设备,使用缺省设备
                disp = getDefaultDisplayDevice();
            }
            layer->updateTransformHint(disp);//设置Layer对象的TransformHint
        }
    }

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



1.4 处理Layer增加情况

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

    // 处理有Layer删除的情况
    if (mLayersRemoved) {
        mLayersRemoved = false;
        mVisibleRegionsDirty = true;
        const size_t count = layers.size();
        for (size_t i=0 ; i& layer(layers[i]);
            if (currentLayers.indexOf(layer) < 0) {
                //如果这个Layer已经不存在了,把它的所在区域设置为需要更新的区域
                const Layer::State& s(layer->getDrawingState());
                Region visibleReg = s.transform.transform(
                        Region(Rect(s.active.w, s.active.h)));
                invalidateLayerStack(s.layerStack, visibleReg);
            }
        }
    }

这段代码处理Layer的增加情况,如果Layer增加了,需要重新计算设备的更新区域,因此把mVisibleRegionsDirty设为true,如果Layer删除了,需要把Layer的可见区域加入到系统需要更新的区域中。

而这里mVisibleRegionsDirty设为true代表Layer需要更新,如果Layer不需要更新的话后面的rebuildLayerStack函数的执行就是空的了。


1.5 设置mDrawingState

commitTransaction();  
  
updateCursorAsync();  
调用commitTransaction和updateCursorAsync函数 commitTransaction函数作用是把mDrawingState的值设置成mCurrentState的值。而updateCursorAsync函数会更新所有显示设备中光标的位置。

1.6 小结

handleTransaction函数的作用的就是处理系统在两次刷新期间的各种变化。SurfaceFlinger模块中不管是SurfaceFlinger类还是Layer类,都采用了双缓冲的方式来保存他们的属性,这样的好处是刚改变SurfaceFlinger对象或者Layer类对象的属性是,不需要上锁,大大的提高了系统效率。只有在最后的图像输出是,才进行一次上锁,并进行内存的属性变化处理。正因此,应用进程必须收到VSync信号才开始改变Surface的内容。


二、handlePageFlip函数

代码如下,这个函数就是更新Layer中的buffer(内容),遍历每个Layer看这个Layer是否有内容更新,就看其hasQueuedFrame函数是否返回true。之前分析过当有更新的话,mQueuedFrames的值会加1.而hasQueuedFrame函数就是看这个值是否为0

bool SurfaceFlinger::handlePageFlip()
{
    Region dirtyRegion;

    bool visibleRegions = false;
    const LayerVector& layers(mDrawingState.layersSortedByZ);
    bool frameQueued = false;

    Vector layersWithQueuedFrames;
    //查找需要更新的Layer
    for (size_t i = 0, count = layers.size(); i& layer(layers[i]);
        if (layer->hasQueuedFrame()) {
            frameQueued = true;
            if (layer->shouldPresentNow(mPrimaryDispSync)) {
                layersWithQueuedFrames.push_back(layer.get());
            } else {
                layer->useEmptyDamage();
            }
        } else {
            layer->useEmptyDamage();
        }
    }
    for (size_t i = 0, count = layersWithQueuedFrames.size() ; ilatchBuffer(visibleRegions));
        layer->useSurfaceDamage();
        const Layer::State& s(layer->getDrawingState());
        invalidateLayerStack(s.layerStack, dirty);
    }

    mVisibleRegionsDirty |= visibleRegions;

    if (frameQueued && layersWithQueuedFrames.empty()) {
        signalLayerUpdate();
    }

    return !layersWithQueuedFrames.empty();
}

hasQueuedFrame函数如下。

    bool hasQueuedFrame() const { return mQueuedFrames > 0 || mSidebandStreamChanged; }
最后把所有需要更新的Layer放在layersWithQueuedFrames,然后调用每个Layer的latchBuffer函数。

调用每个Layer的latchBuffer函数根据返回的更新区域调用invalidateLayerStack来设置更新设备对象的更新区域。

我们先来看看invalidateLayerStack函数,在SurfaceFlinger.cpp中的invalidateLayerStack。先是遍历所有的设备,找到和Layer的layerStack一样的设备,然后调用了DisplayDevice的dirtyRegion.orSelf方法

void SurfaceFlinger::invalidateLayerStack(uint32_t layerStack,
        const Region& dirty) {
    for (size_t dpy=0 ; dpy& hw(mDisplays[dpy]);
        if (hw->getLayerStack() == layerStack) {
            hw->dirtyRegion.orSelf(dirty);
        }
    }
}
orSelf方法,就是把Layer的更新区域 加到 DisplayDevice的dirtyRegion区域上。
Region& Region::orSelf(const Rect& r) {
    return operationSelf(r, op_or);
}

最后我们再来看看latchBuffer函数

Region Layer::latchBuffer(bool& recomputeVisibleRegions)
{
    ATRACE_CALL();

    if (android_atomic_acquire_cas(true, false, &mSidebandStreamChanged) == 0) {
        // mSidebandStreamChanged was true
        mSidebandStream = mSurfaceFlingerConsumer->getSidebandStream();
        if (mSidebandStream != NULL) {
            setTransactionFlags(eTransactionNeeded);
            mFlinger->setTransactionFlags(eTraversalNeeded);
        }
        recomputeVisibleRegions = true;

        const State& s(getDrawingState());
        return s.transform.transform(Region(Rect(s.active.w, s.active.h)));
    }

    Region outDirtyRegion;
    if (mQueuedFrames > 0) { //mQueuedFrames大于0代表有Surface更新的要求
        if (mRefreshPending) {
            return outDirtyRegion;
        }

        // Capture the old state of the layer for comparisons later
        const State& s(getDrawingState());//注意这是使用的DrawingState
        const bool oldOpacity = isOpaque(s);
        sp oldActiveBuffer = mActiveBuffer;

        struct Reject : public SurfaceFlingerConsumer::BufferRejecter {
            ......//定义Reject结构体
        };

        Reject r(mDrawingState, getCurrentState(), recomputeVisibleRegions,
                getProducerStickyTransform() != 0);

        uint64_t maxFrameNumber = 0;
        {
            Mutex::Autolock lock(mQueueItemLock);
            maxFrameNumber = mLastFrameNumberReceived;
        }

        status_t updateResult = mSurfaceFlingerConsumer->updateTexImage(&r,//更新纹理
                mFlinger->mPrimaryDispSync, maxFrameNumber);
        if (updateResult == BufferQueue::PRESENT_LATER) {
            mFlinger->signalLayerUpdate();//如果结果是推迟处理,发送Invalidate消息
            return outDirtyRegion;
        } else if (updateResult == SurfaceFlingerConsumer::BUFFER_REJECTED) {
            // If the buffer has been rejected, remove it from the shadow queue
            // and return early
            Mutex::Autolock lock(mQueueItemLock);
            mQueueItems.removeAt(0);
            android_atomic_dec(&mQueuedFrames);
            return outDirtyRegion;
        } else if (updateResult != NO_ERROR || mUpdateTexImageFailed) {
            // This can occur if something goes wrong when trying to create the
            // EGLImage for this buffer. If this happens, the buffer has already
            // been released, so we need to clean up the queue and bug out
            // early.
            {
                Mutex::Autolock lock(mQueueItemLock);
                mQueueItems.clear();
                android_atomic_and(0, &mQueuedFrames);
            }

            // Once we have hit this state, the shadow queue may no longer
            // correctly reflect the incoming BufferQueue's contents, so even if
            // updateTexImage starts working, the only safe course of action is
            // to continue to ignore updates.
            mUpdateTexImageFailed = true;

            return outDirtyRegion;
        }

        { // Autolock scope
            auto currentFrameNumber = mSurfaceFlingerConsumer->getFrameNumber();

            Mutex::Autolock lock(mQueueItemLock);

            // Remove any stale buffers that have been dropped during
            // updateTexImage
            while (mQueueItems[0].mFrameNumber != currentFrameNumber) {
                mQueueItems.removeAt(0);
                android_atomic_dec(&mQueuedFrames);
            }

            mQueueItems.removeAt(0);
        }


        // Decrement the queued-frames count.  Signal another event if we
        // have more frames pending.
        if (android_atomic_dec(&mQueuedFrames) > 1) {//减少mQueuedFrames的值
            mFlinger->signalLayerUpdate();//如果还有更多frame需要处理,要发消息
        }

        if (updateResult != NO_ERROR) {
            // something happened!
            recomputeVisibleRegions = true;
            return outDirtyRegion;
        }

        //更新mActiveBuffer,得到现在需要输出的图像数据
        mActiveBuffer = mSurfaceFlingerConsumer->getCurrentBuffer();
        if (mActiveBuffer == NULL) {
            return outDirtyRegion;//出错
        }

        mRefreshPending = true;
        mFrameLatencyNeeded = true;
        //下面根据各种情况是否重新计算更新区域
        if (oldActiveBuffer == NULL) {
             // the first time we receive a buffer, we need to trigger a
             // geometry invalidation.
            recomputeVisibleRegions = true;
         }

        Rect crop(mSurfaceFlingerConsumer->getCurrentCrop());
        const uint32_t transform(mSurfaceFlingerConsumer->getCurrentTransform());
        const uint32_t scalingMode(mSurfaceFlingerConsumer->getCurrentScalingMode());
        if ((crop != mCurrentCrop) ||
            (transform != mCurrentTransform) ||
            (scalingMode != mCurrentScalingMode))
        {
            mCurrentCrop = crop;
            mCurrentTransform = transform;
            mCurrentScalingMode = scalingMode;
            recomputeVisibleRegions = true;
        }

        if (oldActiveBuffer != NULL) {
            uint32_t bufWidth  = mActiveBuffer->getWidth();
            uint32_t bufHeight = mActiveBuffer->getHeight();
            if (bufWidth != uint32_t(oldActiveBuffer->width) ||
                bufHeight != uint32_t(oldActiveBuffer->height)) {
                recomputeVisibleRegions = true;
            }
        }

        mCurrentOpacity = getOpacityForFormat(mActiveBuffer->format);
        if (oldOpacity != isOpaque(s)) {
            recomputeVisibleRegions = true;
        }

        // FIXME: postedRegion should be dirty & bounds
        Region dirtyRegion(Rect(s.active.w, s.active.h));

        // transform the dirty region to window-manager space
        outDirtyRegion = (s.transform.transform(dirtyRegion));//返回Layer的更新区域
    }
    return outDirtyRegion;
}

这里我们来看mSurfaceFlingerConsumer->updateTexImage更新纹理

status_t SurfaceFlingerConsumer::updateTexImage(BufferRejecter* rejecter,
        const DispSync& dispSync, uint64_t maxFrameNumber)
{
    ATRACE_CALL();
    Mutex::Autolock lock(mMutex);

    if (mAbandoned) {
        ALOGE("updateTexImage: GLConsumer is abandoned!");
        return NO_INIT;
    }

    // Make sure the EGL state is the same as in previous calls.
    status_t err = checkAndUpdateEglStateLocked();
    if (err != NO_ERROR) {
        return err;
    }

    BufferItem item;

    // Acquire the next buffer.
    // In asynchronous mode the list is guaranteed to be one buffer
    // deep, while in synchronous mode we use the oldest buffer.
    err = acquireBufferLocked(&item, computeExpectedPresent(dispSync),//消费者端取数据
            maxFrameNumber);
    if (err != NO_ERROR) {
        if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
            err = NO_ERROR;
        } else if (err == BufferQueue::PRESENT_LATER) {
            // return the error, without logging
        } else {
            ALOGE("updateTexImage: acquire failed: %s (%d)",
                strerror(-err), err);
        }
        return err;
    }


    // We call the rejecter here, in case the caller has a reason to
    // not accept this buffer.  This is used by SurfaceFlinger to
    // reject buffers which have the wrong size
    int buf = item.mBuf;
    if (rejecter && rejecter->reject(mSlots[buf].mGraphicBuffer, item)) {
        releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer, EGL_NO_SYNC_KHR);
        return BUFFER_REJECTED;
    }

    // Release the previous buffer.
    err = updateAndReleaseLocked(item);
    if (err != NO_ERROR) {
        return err;
    }

    if (!SyncFeatures::getInstance().useNativeFenceSync()) {
        // Bind the new buffer to the GL texture.
        //
        // Older devices require the "implicit" synchronization provided
        // by glEGLImageTargetTexture2DOES, which this method calls.  Newer
        // devices will either call this in Layer::onDraw, or (if it's not
        // a GL-composited layer) not at all.
        err = bindTextureImageLocked();
    }

    return err;
}
我们再来看看updateAndReleaseLocked函数,这个函数释放了buffer,然后更新了mCurrentTexture mCurrentTextureImage等。

status_t GLConsumer::updateAndReleaseLocked(const BufferItem& item)
{
    status_t err = NO_ERROR;

    int buf = item.mBuf;

    if (!mAttached) {
        releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer,
                mEglDisplay, EGL_NO_SYNC_KHR);
        return INVALID_OPERATION;
    }

    err = checkAndUpdateEglStateLocked();
    ......
    err = mEglSlots[buf].mEglImage->createIfNeeded(mEglDisplay, item.mCrop);
    ......
    err = syncForReleaseLocked(mEglDisplay);
    ......

    //释放buffer
    if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
        status_t status = releaseBufferLocked(
                mCurrentTexture, mCurrentTextureImage->graphicBuffer(),
                mEglDisplay, mEglSlots[mCurrentTexture].mEglFence);
        if (status < NO_ERROR) {
            GLC_LOGE("updateAndRelease: failed to release buffer: %s (%d)",
                   strerror(-status), status);
            err = status;
            // keep going, with error raised [?]
        }
    }

    // 更新状态
    mCurrentTexture = buf;
    mCurrentTextureImage = mEglSlots[buf].mEglImage;
    mCurrentCrop = item.mCrop;
    mCurrentTransform = item.mTransform;
    mCurrentScalingMode = item.mScalingMode;
    mCurrentTimestamp = item.mTimestamp;
    mCurrentFence = item.mFence;
    mCurrentFrameNumber = item.mFrameNumber;

    computeCurrentTransformMatrixLocked();

    return err;
}
最后Layer的mActiveBuffer是从mSurfaceFlingerConsumer->getCurrentBuffer(),而就是mCurrentTextureImage变量。

sp GLConsumer::getCurrentBuffer() const {
    Mutex::Autolock lock(mMutex);
    return (mCurrentTextureImage == NULL) ?
            NULL : mCurrentTextureImage->graphicBuffer();
}

LatchBuffer函数调用updateTextImage来得到需要的图像。这里参数r是Reject对象,其作用是判断在缓冲区的尺寸是否符合要求。调用updateTextImage函数如果得到的结果是PRESENT_LATER,表示推迟处理,然后调用signalLayerUpdate函数来发送invalidate消息,这次绘制过程就不处理这个Surface的图像了。

如果不需要推迟处理,把mQueuedFrames的值减1.

最后LatchBuffer函数调用mSurfaceFlingerConsumer的getCurrentBuffer来取回当前的图像缓冲区指针,保存在mActiveBuffer中。



这样经过handleTransaction handlePageFlip两个函数处理SurfaceFlinger中无论是Layer属性的变化还是图像的变化都处理好了,只等VSync信号到来就可以输出了。



三、rebuildLayerStack函数

VSync信号来了之后先是调用的这个函数,前面分析handleTransactionLocked的时候,当mVisibleRegionsDirty为 true代表是要更新Layer,这里上来就是看这个变量是否为true。

void SurfaceFlinger::rebuildLayerStacks() {
    // rebuild the visible layer list per screen
    if (CC_UNLIKELY(mVisibleRegionsDirty)) {//mVisibleRegionsDirty是否为true
        ATRACE_CALL();
        mVisibleRegionsDirty = false;
        invalidateHwcGeometry();
        
        //计算每个显示设备上可见的Layer
        const LayerVector& layers(mDrawingState.layersSortedByZ);
        for (size_t dpy=0 ; dpy > layersSortedByZ;
            const sp& hw(mDisplays[dpy]);
            const Transform& tr(hw->getTransform());
            const Rect bounds(hw->getBounds());
            if (hw->isDisplayOn()) {
                //计算每个layer的可见区域,确定设备需要重新绘制的区域
                SurfaceFlinger::computeVisibleRegions(layers,
                        hw->getLayerStack(), dirtyRegion, opaqueRegion);

                const size_t count = layers.size();
                for (size_t i=0 ; i& layer(layers[i]);
                    const Layer::State& s(layer->getDrawingState());
                    if (s.layerStack == hw->getLayerStack()) {
                        //只需要和显示设备的LayerStack相同的layer
                        Region drawRegion(tr.transform(
                                layer->visibleNonTransparentRegion));
                        drawRegion.andSelf(bounds);
                        if (!drawRegion.isEmpty()) {
                            //如果Layer的显示区域和显示设备的窗口有交集
                            //把Layer加入列表中
                            layersSortedByZ.add(layer);
                        }
                    }
                }
            }
            //设置显示设备的可见Layer列表
            hw->setVisibleLayersSortedByZ(layersSortedByZ);
            hw->undefinedRegion.set(bounds);
            hw->undefinedRegion.subtractSelf(tr.transform(opaqueRegion));
            hw->dirtyRegion.orSelf(dirtyRegion);//设置每个DisplayDevice的drawRegions 加上dirtyRegion区域
        }
    }
}

rebuildLayerStacks函数的作用是重建每个显示设备的可见layer对象列表。其他的说明还是看另一篇博客http://write.blog.csdn.net/postedit?ref=toolbar&ticket=ST-83533-ejxpwYJbCoASdBlu6Tpr-passport.csdn.net


四、setUpHWComposer函数

HWComposer中有一个类型为DisplayData结构的数组mDisplayData[],维护每个显示设备的信息。我们先来看在HWComposer构造函数中有下面这段代码,我们这里mFbDev为空,因此我们遍历每个设备,调用queryDisplayProperties函数。

    if (mFbDev) {
        ALOGD("chenchen mFbDev end");
        ALOG_ASSERT(!(mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)),
                "should only have fbdev if no hwc or hwc is 1.0");

        DisplayData& disp(mDisplayData[HWC_DISPLAY_PRIMARY]);
        disp.connected = true;
        disp.format = mFbDev->format;
        DisplayConfig config = DisplayConfig();
        config.width = mFbDev->width;
        config.height = mFbDev->height;
        config.xdpi = mFbDev->xdpi;
        config.ydpi = mFbDev->ydpi;
        config.refresh = nsecs_t(1e9 / mFbDev->fps);
        disp.configs.push_back(config);
        disp.currentConfig = 0;
    } else if (mHwc) {
        // here we're guaranteed to have at least HWC 1.1
        for (size_t i =0 ; i

下面我们来看queryDisplayProperties函数,通过hwc模块的getDisplayConfigs和getDisplayAttributes方法来获取configs,最后把格式和connect设置为true。

status_t HWComposer::queryDisplayProperties(int disp) {

    LOG_ALWAYS_FATAL_IF(!mHwc || !hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1));

    // use zero as default value for unspecified attributes
    int32_t values[NUM_DISPLAY_ATTRIBUTES - 1];
    memset(values, 0, sizeof(values));

    const size_t MAX_NUM_CONFIGS = 128;
    uint32_t configs[MAX_NUM_CONFIGS] = {0};
    size_t numConfigs = MAX_NUM_CONFIGS;
    status_t err = mHwc->getDisplayConfigs(mHwc, disp, configs, &numConfigs);
    if (err != NO_ERROR) {
        // this can happen if an unpluggable display is not connected
        mDisplayData[disp].connected = false;
        return err;
    }

    mDisplayData[disp].currentConfig = 0;
    for (size_t c = 0; c < numConfigs; ++c) {
        err = mHwc->getDisplayAttributes(mHwc, disp, configs[c],
                DISPLAY_ATTRIBUTES, values);
        // If this is a pre-1.5 HWC, it may not know about color transform, so
        // try again with a smaller set of attributes
        if (err != NO_ERROR) {
            err = mHwc->getDisplayAttributes(mHwc, disp, configs[c],
                    PRE_HWC15_DISPLAY_ATTRIBUTES, values);
        }
        if (err != NO_ERROR) {
            // we can't get this display's info. turn it off.
            mDisplayData[disp].connected = false;
            return err;
        }

        DisplayConfig config = DisplayConfig();
        for (size_t i = 0; i < NUM_DISPLAY_ATTRIBUTES - 1; i++) {
            switch (DISPLAY_ATTRIBUTES[i]) {
                case HWC_DISPLAY_VSYNC_PERIOD:
                    config.refresh = nsecs_t(values[i]);//设置config
                    break;
                case HWC_DISPLAY_WIDTH:
                    config.width = values[i];
                    break;
                case HWC_DISPLAY_HEIGHT:
                    config.height = values[i];
                    break;
                case HWC_DISPLAY_DPI_X:
                    config.xdpi = values[i] / 1000.0f;
                    break;
                case HWC_DISPLAY_DPI_Y:
                    config.ydpi = values[i] / 1000.0f;
                    break;
                case HWC_DISPLAY_COLOR_TRANSFORM:
                    config.colorTransform = values[i];
                    break;
                default:
                    ALOG_ASSERT(false, "unknown display attribute[%zu] %#x",
                            i, DISPLAY_ATTRIBUTES[i]);
                    break;
            }
        }

        if (config.xdpi == 0.0f || config.ydpi == 0.0f) {
            float dpi = getDefaultDensity(config.width, config.height);
            config.xdpi = dpi;
            config.ydpi = dpi;
        }

        mDisplayData[disp].configs.push_back(config);
    }

    // FIXME: what should we set the format to?
    mDisplayData[disp].format = HAL_PIXEL_FORMAT_RGBA_8888;//格式
    mDisplayData[disp].connected = true;//已连接
    return NO_ERROR;
}

我们再来看SurfaceFlinger中init函数,后面创建DisplayDevice过程。

    for (size_t i=0 ; iisConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) {//当前设备连接了,或者是默认设备(即使没有连接)
            // All non-virtual displays are currently considered secure.
            bool isSecure = true;
            createBuiltinDisplayLocked(type);//分配一个token
            wp token = mBuiltinDisplays[i];

            sp producer;
            sp consumer;
            BufferQueue::createBufferQueue(&producer, &consumer,//创建producer consumer
                    new GraphicBufferAlloc());

            sp fbs = new FramebufferSurface(*mHwc, i,
                    consumer);
            int32_t hwcId = allocateHwcDisplayId(type);
            sp hw = new DisplayDevice(this,//创建DisplayDevice
                    type, hwcId, mHwc->getFormat(hwcId), isSecure, token,
                    fbs, producer,
                    mRenderEngine->getEGLConfig());
            if (i > DisplayDevice::DISPLAY_PRIMARY) {
                // FIXME: currently we don't get blank/unblank requests
                // for displays other than the main display, so we always
                // assume a connected display is unblanked.
                ALOGD("marking display %zu as acquired/unblanked", i);
                hw->setPowerMode(HWC_POWER_MODE_NORMAL);
            }
            mDisplays.add(token, hw);//放入mDisplays中
        }
    }

setUpHWComposer函数的作用是更新HWComposer对象中图层对象列表以及图层属性。下面函数先会遍历各个设备DisplayDevice,然后根据可见layer数量,调用createWorkList创建hwc_layer_list_t列表,然后在每个设备上遍历可见layer,将layer的mActiveBuffer设置到HWComposer中去,最后调用了HWComposer的prepare函数。

void SurfaceFlinger::setUpHWComposer() {
    ......
    HWComposer& hwc(getHwComposer());
    if (hwc.initCheck() == NO_ERROR) {
        // build the h/w work list
        if (CC_UNLIKELY(mHwWorkListDirty)) {
            mHwWorkListDirty = false;
            for (size_t dpy=0 ; dpy hw(mDisplays[dpy]);
                const int32_t id = hw->getHwcDisplayId();
                if (id >= 0) {
                    const Vector< sp >& currentLayers(//遍历DisplayDevice所有可见layer
                        hw->getVisibleLayersSortedByZ());
                    const size_t count = currentLayers.size();
                    if (hwc.createWorkList(id, count) == NO_ERROR) {//根据layer数量调用createWorkList创建hwc_layer_list_t列表
                        HWComposer::LayerListIterator cur = hwc.begin(id);
                        const HWComposer::LayerListIterator end = hwc.end(id);
                        for (size_t i=0 ; cur!=end && i& layer(currentLayers[i]);
                            layer->setGeometry(hw, *cur);
                            if (mDebugDisableHWC || mDebugRegion || mDaltonize || mHasColorMatrix) {
                                cur->setSkip(true);
                            }
                        }
                    }
                }
            }
        }

        // set the per-frame data
        for (size_t dpy=0 ; dpy hw(mDisplays[dpy]);
            const int32_t id = hw->getHwcDisplayId();
            if (id >= 0) {
                const Vector< sp >& 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& layer(currentLayers[i]);
                    layer->setPerFrameData(hw, *cur);
                }
            }
        }

        // If possible, attempt to use the cursor overlay on each display.
        for (size_t dpy=0 ; dpy hw(mDisplays[dpy]);
            const int32_t id = hw->getHwcDisplayId();
            if (id >= 0) {
                const Vector< sp >& 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& layer(currentLayers[i]);
                    if (layer->isPotentialCursor()) {
                        cur->setIsCursorLayerHint();
                        break;
                    }
                }
            }
        }

        status_t err = hwc.prepare();
        ALOGE_IF(err, "HWComposer::prepare failed (%s)", strerror(-err));

        for (size_t dpy=0 ; dpy hw(mDisplays[dpy]);
            hw->prepareFrame(hwc);
        }
    }
}
我们先来看下createWorkList函数,我们先为DisplayData的list申请内存,这个内存要先hwc_display_contents_1_t结构体本身的长度加上后面hwc_layer_1_t个数的长度。后面用DisplayData中list中hwLayers最后一个作为DisplayData中的framebufferTarget。 注意到这个细节没有,当支持egl合成的时候,会把numLayers加1,这是因为如果支持egl合成list最后一个layer是egl合成后的buffer用的,所以要增加一个layer,而前面都是普通的layer。

status_t HWComposer::createWorkList(int32_t id, size_t numLayers) {
    if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) {
        return BAD_INDEX;
    }

    if (mHwc) {
        DisplayData& disp(mDisplayData[id]);
        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
            // we need space for the HWC_FRAMEBUFFER_TARGET
            numLayers++;//注意到这个细节没有,当支持egl合成的时候,会把numLayers加1
        }
        if (disp.capacity < numLayers || disp.list == NULL) {//当DisplayData中的list为空,我们就要malloc
            size_t size = sizeof(hwc_display_contents_1_t)
                    + numLayers * sizeof(hwc_layer_1_t);//整个申请内存长度,hwc_display_contents_1_t结构体本身的长度加上后面hwc_layer_1_t个数的长度
            free(disp.list);
            disp.list = (hwc_display_contents_1_t*)malloc(size);//malloc
            disp.capacity = numLayers;
        }
        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
            disp.framebufferTarget = &disp.list->hwLayers[numLayers - 1];
            memset(disp.framebufferTarget, 0, sizeof(hwc_layer_1_t));//DisplayData的framebufferTarget清0
            const DisplayConfig& currentConfig =
                    disp.configs[disp.currentConfig];
            const hwc_rect_t r = { 0, 0,
                    (int) currentConfig.width, (int) currentConfig.height };
            disp.framebufferTarget->compositionType = HWC_FRAMEBUFFER_TARGET;
            disp.framebufferTarget->hints = 0;
            disp.framebufferTarget->flags = 0;
            disp.framebufferTarget->handle = disp.fbTargetHandle;
            disp.framebufferTarget->transform = 0;
            disp.framebufferTarget->blending = HWC_BLENDING_PREMULT;
            if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
                disp.framebufferTarget->sourceCropf.left = 0;
                disp.framebufferTarget->sourceCropf.top = 0;
                disp.framebufferTarget->sourceCropf.right =
                        currentConfig.width;
                disp.framebufferTarget->sourceCropf.bottom =
                        currentConfig.height;
            } else {
                disp.framebufferTarget->sourceCrop = r;
            }
            disp.framebufferTarget->displayFrame = r;
            disp.framebufferTarget->visibleRegionScreen.numRects = 1;
            disp.framebufferTarget->visibleRegionScreen.rects =
                &disp.framebufferTarget->displayFrame;
            disp.framebufferTarget->acquireFenceFd = -1;
            disp.framebufferTarget->releaseFenceFd = -1;
            disp.framebufferTarget->planeAlpha = 0xFF;
        }
        disp.list->retireFenceFd = -1;
        disp.list->flags = HWC_GEOMETRY_CHANGED;
        disp.list->numHwLayers = numLayers;//DisplayData中list中layer的个数
    }
    return NO_ERROR;
}

下面我们来看下DisplayData的数据结构

    struct DisplayData {
        DisplayData();
        ~DisplayData();
        Vector configs;
        size_t currentConfig;
        uint32_t format;    // pixel format from FB hal, for pre-hwc-1.1
        bool connected;
        bool hasFbComp;
        bool hasOvComp;
        size_t capacity;
        hwc_display_contents_1* list;
        hwc_layer_1* framebufferTarget;
        buffer_handle_t fbTargetHandle;
        sp lastRetireFence;  // signals when the last set op retires
        sp lastDisplayFence; // signals when the last set op takes
                                    // effect on screen
        buffer_handle_t outbufHandle;
        sp outbufAcquireFence;

        // protected by mEventControlLock
        int32_t events;
    };

再来看下hwc_display_contents_1。保留了原始的注释,我们先看hwc_display_contents_1,我们先看联合体union,第一个hwc_display_t dpy hwc_surface_t sur这个是EGL使用的,而如果是普通的就使用另外一个联合体outbuf什么的,后面还保存了layer的个数和hwc_layer_1_t 数组的起始地址hwLayers[0]

typedef struct hwc_display_contents_1 {
    /* File descriptor referring to a Sync HAL fence object which will signal
     * when this composition is retired. For a physical display, a composition
     * is retired when it has been replaced on-screen by a subsequent set. For
     * a virtual display, the composition is retired when the writes to
     * outputBuffer are complete and can be read. The fence object is created
     * and returned by the set call; this field will be -1 on entry to prepare
     * and set. SurfaceFlinger will close the returned file descriptor.
     */
    int retireFenceFd;

    union {
        /* Fields only relevant for HWC_DEVICE_VERSION_1_0. */
        struct {
            /* (dpy, sur) is the target of SurfaceFlinger's OpenGL ES
             * composition for HWC_DEVICE_VERSION_1_0. They aren't relevant to
             * prepare. The set call should commit this surface atomically to
             * the display along with any overlay layers.
             */
            hwc_display_t dpy;
            hwc_surface_t sur;
        };

        /* These fields are used for virtual displays when the h/w composer
         * version is at least HWC_DEVICE_VERSION_1_3. */
        struct {
            /* outbuf is the buffer that receives the composed image for
             * virtual displays. Writes to the outbuf must wait until
             * outbufAcquireFenceFd signals. A fence that will signal when
             * writes to outbuf are complete should be returned in
             * retireFenceFd.
             *
             * This field is set before prepare(), so properties of the buffer
             * can be used to decide which layers can be handled by h/w
             * composer.
             *
             * If prepare() sets all layers to FRAMEBUFFER, then GLES
             * composition will happen directly to the output buffer. In this
             * case, both outbuf and the FRAMEBUFFER_TARGET layer's buffer will
             * be the same, and set() has no work to do besides managing fences.
             *
             * If the TARGET_FORCE_HWC_FOR_VIRTUAL_DISPLAYS board config
             * variable is defined (not the default), then this behavior is
             * changed: if all layers are marked for FRAMEBUFFER, GLES
             * composition will take place to a scratch framebuffer, and
             * h/w composer must copy it to the output buffer. This allows the
             * h/w composer to do format conversion if there are cases where
             * that is more desirable than doing it in the GLES driver or at the
             * virtual display consumer.
             *
             * If some or all layers are marked OVERLAY, then the framebuffer
             * and output buffer will be different. As with physical displays,
             * the framebuffer handle will not change between frames if all
             * layers are marked for OVERLAY.
             */
            buffer_handle_t outbuf;

            /* File descriptor for a fence that will signal when outbuf is
             * ready to be written. The h/w composer is responsible for closing
             * this when no longer needed.
             *
             * Will be -1 whenever outbuf is NULL, or when the outbuf can be
             * written immediately.
             */
            int outbufAcquireFenceFd;
        };
    };

    /* List of layers that will be composed on the display. The buffer handles
     * in the list will be unique. If numHwLayers is 0, all composition will be
     * performed by SurfaceFlinger.
     */
    uint32_t flags;
    size_t numHwLayers;//layer个数
    hwc_layer_1_t hwLayers[0];//layer起始地址

} hwc_display_contents_1_t;

再来看下每个layer的数据结构体hwc_layer_1 ,其主要数据在buffer_handle_t handle中,buffer_handle_t 其实就是native_handle_t之前分析过,里面有共享内存的fd和地址。

typedef struct hwc_layer_1 {
    /*
     * compositionType is used to specify this layer's type and is set by either
     * the hardware composer implementation, or by the caller (see below).
     *
     *  This field is always reset to HWC_BACKGROUND or HWC_FRAMEBUFFER
     *  before (*prepare)() is called when the HWC_GEOMETRY_CHANGED flag is
     *  also set, otherwise, this field is preserved between (*prepare)()
     *  calls.
     *
     * HWC_BACKGROUND
     *   Always set by the caller before calling (*prepare)(), this value
     *   indicates this is a special "background" layer. The only valid field
     *   is backgroundColor.
     *   The HWC can toggle this value to HWC_FRAMEBUFFER to indicate it CANNOT
     *   handle the background color.
     *
     *
     * HWC_FRAMEBUFFER_TARGET
     *   Always set by the caller before calling (*prepare)(), this value
     *   indicates this layer is the framebuffer surface used as the target of
     *   OpenGL ES composition. If the HWC sets all other layers to HWC_OVERLAY
     *   or HWC_BACKGROUND, then no OpenGL ES composition will be done, and
     *   this layer should be ignored during set().
     *
     *   This flag (and the framebuffer surface layer) will only be used if the
     *   HWC version is HWC_DEVICE_API_VERSION_1_1 or higher. In older versions,
     *   the OpenGL ES target surface is communicated by the (dpy, sur) fields
     *   in hwc_compositor_device_1_t.
     *
     *   This value cannot be set by the HWC implementation.
     *
     *
     * HWC_FRAMEBUFFER
     *   Set by the caller before calling (*prepare)() ONLY when the
     *   HWC_GEOMETRY_CHANGED flag is also set.
     *
     *   Set by the HWC implementation during (*prepare)(), this indicates
     *   that the layer will be drawn into the framebuffer using OpenGL ES.
     *   The HWC can toggle this value to HWC_OVERLAY to indicate it will
     *   handle the layer.
     *
     *
     * HWC_OVERLAY
     *   Set by the HWC implementation during (*prepare)(), this indicates
     *   that the layer will be handled by the HWC (ie: it must not be
     *   composited with OpenGL ES).
     *
     *
     * HWC_SIDEBAND
     *   Set by the caller before calling (*prepare)(), this value indicates
     *   the contents of this layer come from a sideband video stream.
     *
     *   The h/w composer is responsible for receiving new image buffers from
     *   the stream at the appropriate time (e.g. synchronized to a separate
     *   audio stream), compositing them with the current contents of other
     *   layers, and displaying the resulting image. This happens
     *   independently of the normal prepare/set cycle. The prepare/set calls
     *   only happen when other layers change, or when properties of the
     *   sideband layer such as position or size change.
     *
     *   If the h/w composer can't handle the layer as a sideband stream for
     *   some reason (e.g. unsupported scaling/blending/rotation, or too many
     *   sideband layers) it can set compositionType to HWC_FRAMEBUFFER in
     *   (*prepare)(). However, doing so will result in the layer being shown
     *   as a solid color since the platform is not currently able to composite
     *   sideband layers with the GPU. This may be improved in future
     *   versions of the platform.
     *
     *
     * HWC_CURSOR_OVERLAY
     *   Set by the HWC implementation during (*prepare)(), this value
     *   indicates the layer's composition will now be handled by the HWC.
     *   Additionally, the client can now asynchronously update the on-screen
     *   position of this layer using the setCursorPositionAsync() api.
     */
    int32_t compositionType;

    /*
     * hints is bit mask set by the HWC implementation during (*prepare)().
     * It is preserved between (*prepare)() calls, unless the
     * HWC_GEOMETRY_CHANGED flag is set, in which case it is reset to 0.
     *
     * see hwc_layer_t::hints
     */
    uint32_t hints;

    /* see hwc_layer_t::flags */
    uint32_t flags;

    union {
        /* color of the background.  hwc_color_t.a is ignored */
        hwc_color_t backgroundColor;

        struct {
            union {
                /* When compositionType is HWC_FRAMEBUFFER, HWC_OVERLAY,
                 * HWC_FRAMEBUFFER_TARGET, this is the handle of the buffer to
                 * compose. This handle is guaranteed to have been allocated
                 * from gralloc using the GRALLOC_USAGE_HW_COMPOSER usage flag.
                 * If the layer's handle is unchanged across two consecutive
                 * prepare calls and the HWC_GEOMETRY_CHANGED flag is not set
                 * for the second call then the HWComposer implementation may
                 * assume that the contents of the buffer have not changed. */
                buffer_handle_t handle;

                /* When compositionType is HWC_SIDEBAND, this is the handle
                 * of the sideband video stream to compose. */
                const native_handle_t* sidebandStream;
            };

            /* transformation to apply to the buffer during composition */
            uint32_t transform;

            /* blending to apply during composition */
            int32_t blending;

            /* area of the source to consider, the origin is the top-left corner of
             * the buffer. As of HWC_DEVICE_API_VERSION_1_3, sourceRect uses floats.
             * If the h/w can't support a non-integer source crop rectangle, it should
             * punt to OpenGL ES composition.
             */
            union {
                // crop rectangle in integer (pre HWC_DEVICE_API_VERSION_1_3)
                hwc_rect_t sourceCropi;
                hwc_rect_t sourceCrop; // just for source compatibility
                // crop rectangle in floats (as of HWC_DEVICE_API_VERSION_1_3)
                hwc_frect_t sourceCropf;
            };

            /* where to composite the sourceCrop onto the display. The sourceCrop
             * is scaled using linear filtering to the displayFrame. The origin is the
             * top-left corner of the screen.
             */
            hwc_rect_t displayFrame;

            /* visible region in screen space. The origin is the
             * top-left corner of the screen.
             * The visible region INCLUDES areas overlapped by a translucent layer.
             */
            hwc_region_t visibleRegionScreen;

            /* Sync fence object that will be signaled when the buffer's
             * contents are available. May be -1 if the contents are already
             * available. This field is only valid during set(), and should be
             * ignored during prepare(). The set() call must not wait for the
             * fence to be signaled before returning, but the HWC must wait for
             * all buffers to be signaled before reading from them.
             *
             * HWC_FRAMEBUFFER layers will never have an acquire fence, since
             * reads from them are complete before the framebuffer is ready for
             * display.
             *
             * HWC_SIDEBAND layers will never have an acquire fence, since
             * synchronization is handled through implementation-defined
             * sideband mechanisms.
             *
             * The HWC takes ownership of the acquireFenceFd and is responsible
             * for closing it when no longer needed.
             */
            int acquireFenceFd;

            /* During set() the HWC must set this field to a file descriptor for
             * a sync fence object that will signal after the HWC has finished
             * reading from the buffer. The field is ignored by prepare(). Each
             * layer should have a unique file descriptor, even if more than one
             * refer to the same underlying fence object; this allows each to be
             * closed independently.
             *
             * If buffer reads can complete at significantly different times,
             * then using independent fences is preferred. For example, if the
             * HWC handles some layers with a blit engine and others with
             * overlays, then the blit layers can be reused immediately after
             * the blit completes, but the overlay layers can't be reused until
             * a subsequent frame has been displayed.
             *
             * Since HWC doesn't read from HWC_FRAMEBUFFER layers, it shouldn't
             * produce a release fence for them. The releaseFenceFd will be -1
             * for these layers when set() is called.
             *
             * Since HWC_SIDEBAND buffers don't pass through the HWC client,
             * the HWC shouldn't produce a release fence for them. The
             * releaseFenceFd will be -1 for these layers when set() is called.
             *
             * The HWC client taks ownership of the releaseFenceFd and is
             * responsible for closing it when no longer needed.
             */
            int releaseFenceFd;

            /*
             * Availability: HWC_DEVICE_API_VERSION_1_2
             *
             * Alpha value applied to the whole layer. The effective
             * value of each pixel is computed as:
             *
             *   if (blending == HWC_BLENDING_PREMULT)
             *      pixel.rgb = pixel.rgb * planeAlpha / 255
             *   pixel.a = pixel.a * planeAlpha / 255
             *
             * Then blending proceeds as usual according to the "blending"
             * field above.
             *
             * NOTE: planeAlpha applies to YUV layers as well:
             *
             *   pixel.rgb = yuv_to_rgb(pixel.yuv)
             *   if (blending == HWC_BLENDING_PREMULT)
             *      pixel.rgb = pixel.rgb * planeAlpha / 255
             *   pixel.a = planeAlpha
             *
             *
             * IMPLEMENTATION NOTE:
             *
             * If the source image doesn't have an alpha channel, then
             * the h/w can use the HWC_BLENDING_COVERAGE equations instead of
             * HWC_BLENDING_PREMULT and simply set the alpha channel to
             * planeAlpha.
             *
             * e.g.:
             *
             *   if (blending == HWC_BLENDING_PREMULT)
             *      blending = HWC_BLENDING_COVERAGE;
             *   pixel.a = planeAlpha;
             *
             */
            uint8_t planeAlpha;

            /* Pad to 32 bits */
            uint8_t _pad[3];

            /*
             * Availability: HWC_DEVICE_API_VERSION_1_5
             *
             * This defines the region of the source buffer that has been
             * modified since the last frame.
             *
             * If surfaceDamage.numRects > 0, then it may be assumed that any
             * portion of the source buffer not covered by one of the rects has
             * not been modified this frame. If surfaceDamage.numRects == 0,
             * then the whole source buffer must be treated as if it had been
             * modified.
             *
             * If the layer's contents are not modified relative to the prior
             * prepare/set cycle, surfaceDamage will contain exactly one empty
             * rect ([0, 0, 0, 0]).
             *
             * The damage rects are relative to the pre-transformed buffer, and
             * their origin is the top-left corner.
             */
            hwc_region_t surfaceDamage;
        };
    };

#ifdef __LP64__
    /*
     * For 64-bit mode, this struct is 120 bytes (and 8-byte aligned), and needs
     * to be padded as such to maintain binary compatibility.
     */
    uint8_t reserved[120 - 112];
#else
    /*
     * For 32-bit mode, this struct is 96 bytes, and needs to be padded as such
     * to maintain binary compatibility.
     */
    uint8_t reserved[96 - 84];
#endif

} hwc_layer_1_t;

回到setUpHWComposer函数,下面是变量所有的设备上的layer调用其setPerFrameData函数。

在分析setPerFrameData之前我们先分析下setUpHWComposer中的遍历Layer时候用到的cur和end。我把这段代码单独拿出来。

                HWComposer::LayerListIterator cur = hwc.begin(id);
                const HWComposer::LayerListIterator end = hwc.end(id);
                for (size_t i=0 ; cur!=end && i& layer(currentLayers[i]);
                    layer->setPerFrameData(hw, *cur);
                }
看下HWComposer中的begin函数

HWComposer::LayerListIterator HWComposer::begin(int32_t id) {
    return getLayerIterator(id, 0);
}

再来看下getLayerIterator函数,正常应该是最后一个分支。注意这个时候index是0

HWComposer::LayerListIterator HWComposer::getLayerIterator(int32_t id, size_t index) {
    if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) {
        return LayerListIterator();
    }
    const DisplayData& disp(mDisplayData[id]);
    if (!mHwc || !disp.list || index > disp.list->numHwLayers) {
        return LayerListIterator();
    }
    return LayerListIterator(new HWCLayerVersion1(mHwc, disp.list->hwLayers), index);
}
新建了一个LayerListIterator,这里面HWCLayerVersion1就是mLayerList, index就是mIndex. 我们看下*符号的重载,因为我们后面用到了,就是mLayerList。

    class LayerListIterator {
        friend class HWComposer;
        HWCLayer* const mLayerList;
        size_t mIndex;

        LayerListIterator() : mLayerList(NULL), mIndex(0) { }

        LayerListIterator(HWCLayer* layer, size_t index)
            : mLayerList(layer), mIndex(index) { }

        // we don't allow assignment, because we don't need it for now
        LayerListIterator& operator = (const LayerListIterator& rhs);

    public:
        // copy operators
        LayerListIterator(const LayerListIterator& rhs)
            : mLayerList(HWCLayer::copy(rhs.mLayerList)), mIndex(rhs.mIndex) {
        }

        ~LayerListIterator() { delete mLayerList; }

        // pre-increment
        LayerListIterator& operator++() {
            mLayerList->setLayer(++mIndex);
            return *this;
        }

        // dereference
        HWCLayerInterface& operator * () { return *mLayerList; }
        HWCLayerInterface* operator -> () { return mLayerList; }

        // comparison
        bool operator == (const LayerListIterator& rhs) const {
            return mIndex == rhs.mIndex;
        }
        bool operator != (const LayerListIterator& rhs) const {
            return !operator==(rhs);
        }
    };
而上面的mLayerList就是HWCLayerVersion1对象。

而我们再来看看下HWComposer中的end函数,end函数和begin很像只是在调用getLayerIterator的时候,begin传入0,end传入layer的最后一位。最后就是mIndex成员变量不一样

HWComposer::LayerListIterator HWComposer::end(int32_t id) {
    size_t numLayers = 0;
    if (uint32_t(id) <= 31 && mAllocatedDisplayIDs.hasBit(id)) {
        const DisplayData& disp(mDisplayData[id]);
        if (mHwc && disp.list) {
            numLayers = disp.list->numHwLayers;//获取到list中laye的个数
            if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
                // with HWC 1.1, the last layer is always the HWC_FRAMEBUFFER_TARGET,
                // which we ignore when iterating through the layer list.
                ALOGE_IF(!numLayers, "mDisplayData[%d].list->numHwLayers is 0", id);
                if (numLayers) {
                    numLayers--;//变成最后一位
                }
            }
        }
    }
    return getLayerIterator(id, numLayers);//和上面一样,只是传入的index不一样。
}

我们再来看LayerListIterator操作符++的重载,会调用mLayerList->setLayer函数

        LayerListIterator& operator++() {
            mLayerList->setLayer(++mIndex);
            return *this;
        }
setLayer会从mLayerList中设置当前的mCurrentLayer,通过mLayerList, 这个变量就是disp.list->hwLayers

    virtual status_t setLayer(size_t index) {
        mCurrentLayer = &mLayerList[index];
        return NO_ERROR;
    }
这样准备工作就好了,我们再来分析Layer的setPerFrameData函数,主要就是调用了HWCLayerVersion1的setBuffer函数

void Layer::setPerFrameData(const sp& hw,
        HWComposer::HWCLayerInterface& layer) {
    // we have to set the visible region on every frame because
    // we currently free it during onLayerDisplayed(), which is called
    // after HWComposer::commit() -- every frame.
    // Apply this display's projection's viewport to the visible region
    // before giving it to the HWC HAL.
    const Transform& tr = hw->getTransform();
    Region visible = tr.transform(visibleRegion.intersect(hw->getViewport()));
    layer.setVisibleRegionScreen(visible);
    layer.setSurfaceDamage(surfaceDamageRegion);

    if (mSidebandStream.get()) {
        layer.setSidebandStream(mSidebandStream);
    } else {
        // NOTE: buffer can be NULL if the client never drew into this
        // layer yet, or if we ran out of memory
        layer.setBuffer(mActiveBuffer);
    }
}
再来看HWCLayerVersion1的setBuffer函数,调用getLayer函数设置其handle,而getLayer就是mCurrentLayer。之前mCurrentLayer会一个个遍历各个Layer,这样就把所有的layer都设置其handle,就是hwc_layer_1_t中的handle。
    virtual void setBuffer(const sp& buffer) {
        if (buffer == 0 || buffer->handle == 0) {
            getLayer()->compositionType = HWC_FRAMEBUFFER;
            getLayer()->flags |= HWC_SKIP_LAYER;
            getLayer()->handle = 0;
        } else {
            if (getLayer()->compositionType == HWC_SIDEBAND) {
                // If this was a sideband layer but the stream was removed, reset
                // it to FRAMEBUFFER. The HWC can change it to OVERLAY in prepare.
                getLayer()->compositionType = HWC_FRAMEBUFFER;
            }
            getLayer()->handle = buffer->handle;
        }
    }
最后会调用HWComposer的prepare函数,我们再来看下这个函数。这里我们先将DisplayData的framebufferTarget的composition设置为HWC_FRAMEBUFFER_TARGET,然后将每个DisplayData的list放入mList中。最后调用了mHwc的prepare函数。
status_t HWComposer::prepare() {
    Mutex::Autolock _l(mDisplayLock);
    for (size_t i=0 ; icompositionType = HWC_FRAMEBUFFER_TARGET;
        }
        if (!disp.connected && disp.list != NULL) {
            ALOGW("WARNING: disp %zu: connected, non-null list, layers=%zu",
                  i, disp.list->numHwLayers);
        }
        mLists[i] = disp.list;//DisplayData的list就是mList的一个组员
        if (mLists[i]) {
            if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
                mLists[i]->outbuf = disp.outbufHandle;
                mLists[i]->outbufAcquireFenceFd = -1;
            } else if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
                // garbage data to catch improper use
                mLists[i]->dpy = (hwc_display_t)0xDEADBEEF;
                mLists[i]->sur = (hwc_surface_t)0xDEADBEEF;
            } else {
                mLists[i]->dpy = EGL_NO_DISPLAY;
                mLists[i]->sur = EGL_NO_SURFACE;
            }
        }
    }

    int err = mHwc->prepare(mHwc, mNumDisplays, mLists);//调用Hwc模块的prepare函数
    ALOGE_IF(err, "HWComposer: prepare failed (%s)", strerror(-err));

    if (err == NO_ERROR) {
        // here we're just making sure that "skip" layers are set
        // to HWC_FRAMEBUFFER and we're also counting how many layers
        // we have of each type.
        //
        // If there are no window layers, we treat the display has having FB
        // composition, because SurfaceFlinger will use GLES to draw the
        // wormhole region.
        for (size_t i=0 ; inumHwLayers ; i++) {
                    hwc_layer_1_t& l = disp.list->hwLayers[i];

                    //ALOGD("prepare: %d, type=%d, handle=%p",
                    //        i, l.compositionType, l.handle);

                    if (l.flags & HWC_SKIP_LAYER) {
                        l.compositionType = HWC_FRAMEBUFFER;
                    }
                    if (l.compositionType == HWC_FRAMEBUFFER) {
                        disp.hasFbComp = true;
                    }
                    if (l.compositionType == HWC_OVERLAY) {
                        disp.hasOvComp = true;
                    }
                    if (l.compositionType == HWC_CURSOR_OVERLAY) {
                        disp.hasOvComp = true;
                    }
                }
                if (disp.list->numHwLayers == (disp.framebufferTarget ? 1 : 0)) {
                    disp.hasFbComp = true;
                }
            } else {
                disp.hasFbComp = true;
            }
        }
    }
    return (status_t)err;
}
mHwc的prepare主要将每个Layer的composition设置为HWC_FRAMEBUFFER。






你可能感兴趣的:(android显示系统)