android 使用SurfaceFlinger 服务的流程分析,基于4.4(三)----图像的输出过程

经过前面两篇的介绍,现在可以分析surfaceflinger 的处理UI buffer的流程了

目录

一、onMessageReceived 

1、handleMessageTransaction()

2、handleMessageInvalidate():

3、 signalRefresh();

 ① preComposition():

② rebuildLayerStacks():

③setUpHWComposer

④doComposition


一、onMessageReceived 

通过vsync机制知道,最终会跑到onMessageReceived函数 ::INVALIDATE这里,进行图像输出的准备工作。

void SurfaceFlinger::onMessageReceived(int32_t what) {
    ATRACE_CALL();
    switch (what) {
    case MessageQueue::TRANSACTION:
        handleMessageTransaction();
        break;
    case MessageQueue::INVALIDATE:
        handleMessageTransaction();
        handleMessageInvalidate();
        signalRefresh();
        break;
    case MessageQueue::REFRESH:
        handleMessageRefresh();
        break;
    }
}

case MessageQueue::INVALIDATE:会调用三个方法,分别看一下:

1、handleMessageTransaction()

void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
{
    .....
    /*1、
     * Traversal of the children
     * (perform the transaction for each of them if needed)
     */
    if (transactionFlags & eTraversalNeeded) {
        for (size_t i=0 ; i<count ; i++) {//这里遍历每一个Layer,根据eTraversalNeeded标志来决定是否要检查Layer对象。如果Layer中有eTransactionNeeded标志,则返回非0值,然后调用它的doTransaction函数
            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)//Layer的doTransaction函数返回的flags如果有eVisibleRegion,则说明该Layer需要更新,mVisibleRegionsDirty设置为true
                mVisibleRegionsDirty = true;
        }
    }
    /*2、
     * Perform display own transactions if needed
     */
    if (transactionFlags & eDisplayTransactionNeeded) {
        // here we take advantage of Vector's copy-on-write semantics to
        // improve performance by skipping the transaction entirely when
        // know that the lists are identical
        //得到当前显示设备列表和之前使用的显示设备列表
        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();//以前显示设备的数量

            // find the displays that were removed
            // (ie: in drawing state but not in current state)
            // also handle displays that changed
            // (ie: displays that are in both lists)
            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()) {
                        // Call makeCurrent() on the primary display so we can
                        // be sure that nothing associated with this display
                        // is current.
                        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()) {
                        // 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) {//两个对象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);
                        }
                    }
                }
            }
            //处理显示设备增加的情况。。。
            // find displays that were added
            // (ie: in current state but not in drawing state)
            for (size_t i=0 ; i<cc ; i++) {

            ...............................
            
    }
    3、
//这段代码根据每种显示设备的不同,设置和显示设备关联在一起的Layer(主要看Layer的layerStack是否和DisplayDevice的layerStack一致)的TransformHint(主要指设备的显示方向orientation)
    if (transactionFlags & (eTraversalNeeded|eDisplayTransactionNeeded)) {
        // The transform hint might have changed for some layers
        // (either because a display has changed, or because a layer
        // as changed).
       ..............................
       layer->updateTransformHint(disp);//设置Layer对象的TransformHint
    }

    /*4、
     * Perform our own transaction if needed
     */
    const LayerVector& layers(mDrawingState.layersSortedByZ);
    if (currentLayers.size() > layers.size()) {//如果有Layer加入,设置需要更新 
        // layers have been added
        mVisibleRegionsDirty = true;
    }
    // some layers might have been removed, so
    // we need to update the regions they're exposing.
    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]);
            if (currentLayers.indexOf(layer) < 0) {//如果这个Layer不存在,则把它的所在区域设置为需要更新的区域
                // this layer is not visible anymore
                // TODO: we could traverse the tree from front to back and
                //       compute the actual visible region
                // TODO: we could cache the transformed region
                const Layer::State& s(layer->getDrawingState());
                Region visibleReg = s.transform.transform(
                        Region(Rect(s.active.w, s.active.h)));
                invalidateLayerStack(s.layerStack, visibleReg);
            }
        }

    }

    commitTransaction();//commitTransaction函数最关键的作用是把mDrawingState的值设置成mCurrentState的值。
}

handleTransactionLocked 做了下面几件事:

①在 handleTransactionLocked 函数里面遍历每一个children,调用 layer->doTransaction(0),查看layer是否发生改变,如果是就把 mVisibleRegionsDirty 置为 true  。

②处理显示设备相关的事务,add、remove、change等。

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

③layer的角度发生变化处理。

④surfaceflinger 本身的事务处理,如layer的添加、删除等。

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

①.1 分析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) ||
                             (c.requested.h != s.requested.h);

    if (sizeChanged) {//如果两个对象的大小不相等,说明Layer的尺寸发生变化
        // the size changed, we need to ask our client to request a new buffer
       

        // record the new size, form this point on, when the client request
        // a buffer, it'll get the new size.
        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);

        if (resizePending) {
            // don't let Layer::doTransaction update the drawing state
            // if we have a pending resize, unless we are in fixed-size mode.
            // the drawing state will be updated only once we receive a buffer
            // with the correct size.
            //
            // in particular, we want to make sure the clip (which is part
            // of the geometry state) is latched together with the size but is
            // latched immediately when no resizing is involved.

            flags |= eDontUpdateGeometryState;
        }
    }

    // always set active to requested, unless we're asked not to
    // this is used by Layer, which special cases resizes.
    if (flags & eDontUpdateGeometryState)  {
    } else {如果没有eDontUpdateGeometryState标志,更新active的值为request
        Layer::State& editCurrentState(getCurrentState());
        editCurrentState.active = c.requested;
    }

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

    if (c.sequence != s.sequence) {//如果当前state的sequence和以前state的sequence不等,设置更新标志
        // invalidate and recompute the visible regions if needed
        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));
    }

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

其中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; // changes when visible regions can change
        Transform transform;//序列值,Layer的属性变化一次,这个值就加1
        // the transparentRegion hint is a bit special, it's latched only
        // when we receive a buffer -- this is because it's "content"
        // dependent.
        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,定义在surfaceFlinger.h里面 ,代码如下:

    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;
    };

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

 

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

 

 

 

2、handleMessageInvalidate():
 

handleMessageInvalidate 里面主要干的事情是,让原来的图像数据失效,准备好新的图像数据,主要是在SurfaceFlingerConsumer 的那几步,也就是updateTextImage里面做的那几步。

这里解释一下UML里面几个重要的函数:

void SurfaceFlinger::handlePageFlip()
{
    Region dirtyRegion;

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

    // Store the set of layers that need updates. This set must not change as
    // buffers are being latched, as this could result in a deadlock.
    // Example: Two producers share the same command stream and:
    // 1.) Layer 0 is latched
    // 2.) Layer 0 gets a new frame
    // 2.) Layer 1 gets a new frame
    // 3.) Layer 1 is latched.
    // Display is now waiting on Layer 1's frame, which is behind layer 0's
    // second frame. But layer 0's second frame could be waiting on display.
    Vector<Layer*> layersWithQueuedFrames;
    for (size_t i = 0, count = layers.size(); i<count ; i++) {
        const sp<Layer>& layer(layers[i]);
        if (layer->hasQueuedFrame())//确定这个Layer对象是否有需要更新的图层
            layersWithQueuedFrames.push_back(layer.get());//把需要更新的Layer对象放到layersWithQueuedFrames中
    }
    for (size_t i = 0, count = layersWithQueuedFrames.size() ; i<count ; i++) {
        Layer* layer = layersWithQueuedFrames[i];
         //更新Layer对象的latchBuffer函数
        const Region dirty(layer->latchBuffer(visibleRegions));
        const Layer::State& s(layer->getDrawingState());
        //设置更新设备对象的更新区域
        invalidateLayerStack(s.layerStack, dirty);
    }

    mVisibleRegionsDirty |= visibleRegions;
}

layer的hasQueuedFrame()的代码实现如下:

bool hasQueuedFrame() const { return mQueuedFrames > 0 || mSidebandStreamChanged; }

只要Surface有数据写入,就会调用Layer的onFrameAvailable函数,然后mQueuedFrames值加1。

latchBuffer:

Region Layer::latchBuffer(bool& recomputeVisibleRegions)
{
    ...
 
    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());
        const bool oldOpacity = isOpaque(s);
        sp<GraphicBuffer> oldActiveBuffer = mActiveBuffer;
        
        struct Reject : public SurfaceFlingerConsumer::BufferRejecter {
            //定义Reject结构体...
        };
 
        Reject r(mDrawingState, getCurrentState(), recomputeVisibleRegions,
                getProducerStickyTransform() != 0);
 
        //更新纹理,得到需要的图像
        status_t updateResult = mSurfaceFlingerConsumer->updateTexImage(&r,
                mFlinger->mPrimaryDispSync);
        //如果结果是推迟处理,发送Invalidate消息  
        if (updateResult == BufferQueue::PRESENT_LATER) {
            mFlinger->signalLayerUpdate();
            return outDirtyRegion;
        }
 
        { // Autolock scope
            Mutex::Autolock lock(mQueueItemLock);
            mQueueItems.removeAt(0);
        }
 
        //减少mQueuedFrames的值
        if (android_atomic_dec(&mQueuedFrames) > 1) {
            //如果还有更多frame需要处理,要发消息  
            mFlinger->signalLayerUpdate();
        }
 
        if (updateResult != NO_ERROR) {
            recomputeVisibleRegions = true;
            return outDirtyRegion;
        }
 
        //更新mActiveBuffer,得到现在需要输出的图像数据
        mActiveBuffer = mSurfaceFlingerConsumer->getCurrentBuffer();
        if (mActiveBuffer == NULL) {
            return outDirtyRegion;//出错
        }
 
        mRefreshPending = true;
        mFrameLatencyNeeded = true;
        //下面根据各种情况是否重新计算更新区域
        if (oldActiveBuffer == NULL) {
            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;
        }
 
        Region dirtyRegion(Rect(s.active.w, s.active.h));
        outDirtyRegion = (s.transform.transform(dirtyRegion));
    }
    return outDirtyRegion;
}

latchBuffer函数调用updateTextImage来得到需要的图像纹理。这里参数r是Reject对象,其作用是判断在缓冲区的尺寸是否符合要求。updateTextImage的代码实现如下:

status_t SurfaceFlingerConsumer::updateTexImage(BufferRejecter* rejecter)
{
    ATRACE_CALL();
    ALOGV("updateTexImage");
    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;
    }

    BufferQueue::BufferItem item;

    // 1、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());
    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 NO_ERROR;
    }

    //2、 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.
        //3、
        err = bindTextureImageLocked();
    }

    return err;
}

在看 bindTextureImageLocked 之前,先看看acquireBufferLocked、releaseBufferLocked两函数:

但是在这之前还要了解一下Android 的buffer状态图画 :

APP 作为我们的生产者,他会从FREE状态里面的buffer,dequeue 一个出来,向其填充数据,但APP 调用surface->unlock,的时候,DEQUEUED状态的buffer会变成QUEUED转态的buffer,当执行到updateTextImage 函数时,我们的消费者,会从QUEUED状态里面的buffer acquire 一个出来,变成ACQUIRED状态,当消费完之后会调用releaseBufferLocked,将ACQUIRED转态的buffer release掉,又变回FREE状态。下次生产者又可以拿来用了。

PS 注: QueueBuffer 的使用过程的4种状态:

( 1)FREE表示该Buffer没有被使用,且内容为空

( 2 ) DEQUEUED表示该Buffer正在被内容生产者绘制

( 3 ) QUEUED表示该Buffer已经被绘制了内容,放入BufferQueue,等待被显示(或者下一步处理)

( 4 ) ACQUIRED表示该Buffer正在被消费者拿去做显示(或者下一步处理)

 

acquireBufferLocked 会调用到 ConsumerBase::acquireBufferLocked  函数如下:

status_t ConsumerBase::acquireBufferLocked(BufferQueue::BufferItem *item,
        nsecs_t presentWhen) {
    status_t err = mConsumer->acquireBuffer(item, presentWhen);
    if (err != NO_ERROR) {
        return err;
    }

    if (item->mGraphicBuffer != NULL) {
        mSlots[item->mBuf].mGraphicBuffer = item->mGraphicBuffer;
    }

    mSlots[item->mBuf].mFrameNumber = item->mFrameNumber;
    mSlots[item->mBuf].mFence = item->mFence;

    CB_LOGV("acquireBufferLocked: -> slot=%d/%" PRIu64,
            item->mBuf, item->mFrameNumber);

    return OK;
}

可以看见 这个函数里面调用了 mConsumer->acquireBuffer(item, presentWhen); mConsumer 是谁?mConsumer 就是 BufferQueueConsumer 类的对象,怎么来的看下:

void Layer::onFirstRef() {
    // Creates a custom BufferQueue for SurfaceFlingerConsumer to use
    sp<IGraphicBufferProducer> producer;
    sp<IGraphicBufferConsumer> consumer;
    BufferQueue::createBufferQueue(&producer, &consumer);
    mProducer = new MonitoredProducer(producer, mFlinger);
    mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(consumer, mTextureName);
    mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0));
    mSurfaceFlingerConsumer->setContentsChangedListener(this);
    mSurfaceFlingerConsumer->setName(mName);

#ifdef TARGET_DISABLE_TRIPLE_BUFFERING
#warning "disabling triple buffering"
    mSurfaceFlingerConsumer->setDefaultMaxBufferCount(2);
#else
    mSurfaceFlingerConsumer->setDefaultMaxBufferCount(3);
#endif

    const sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice());
    updateTransformHint(hw);
}

即是在创建 SurfaceControl 的时候,触发 Layer::onFirstRef ()时,mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(consumer, mTextureName);传进去的consumer,最终复制给了mConsumer,所以mConsumer 就是BufferQueueConsumer。所以mConsumerr->acquireBuffer(item, presentWhen)最终会调用到BufferQueueConsumer::acquireBuffer()

status_t BufferQueueConsumer::acquireBuffer(BufferItem* outBuffer,
        nsecs_t expectedPresent) {
    ATRACE_CALL();
    Mutex::Autolock lock(mCore->mMutex);

    // Check that the consumer doesn't currently have the maximum number of
    // buffers acquired. We allow the max buffer count to be exceeded by one
    // buffer so that the consumer can successfully set up the newly acquired
    // buffer before releasing the old one.
    int numAcquiredBuffers = 0;
    for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
        if (mSlots[s].mBufferState == BufferSlot::ACQUIRED) {
            ++numAcquiredBuffers;
        }
    }
    if (numAcquiredBuffers >= mCore->mMaxAcquiredBufferCount + 1) {
        BQ_LOGE("acquireBuffer: max acquired buffer count reached: %d (max %d)",
                numAcquiredBuffers, mCore->mMaxAcquiredBufferCount);
        return INVALID_OPERATION;
    }

    // Check if the queue is empty.
    // In asynchronous mode the list is guaranteed to be one buffer deep,
    // while in synchronous mode we use the oldest buffer.
    if (mCore->mQueue.empty()) {
        return NO_BUFFER_AVAILABLE;
    }

    BufferQueueCore::Fifo::iterator front(mCore->mQueue.begin());

    // If expectedPresent is specified, we may not want to return a buffer yet.
    // If it's specified and there's more than one buffer queued, we may want
    // to drop a buffer.
    if (expectedPresent != 0) {
        const int MAX_REASONABLE_NSEC = 1000000000ULL; // 1 second

        // The 'expectedPresent' argument indicates when the buffer is expected
        // to be presented on-screen. If the buffer's desired present time is
        // earlier (less) than expectedPresent -- meaning it will be displayed
        // on time or possibly late if we show it as soon as possible -- we
        // acquire and return it. If we don't want to display it until after the
        // expectedPresent time, we return PRESENT_LATER without acquiring it.
        //
        // To be safe, we don't defer acquisition if expectedPresent is more
        // than one second in the future beyond the desired present time
        // (i.e., we'd be holding the buffer for a long time).
        //
        // NOTE: Code assumes monotonic time values from the system clock
        // are positive.

        // Start by checking to see if we can drop frames. We skip this check if
        // the timestamps are being auto-generated by Surface. If the app isn't
        // generating timestamps explicitly, it probably doesn't want frames to
        // be discarded based on them.
        while (mCore->mQueue.size() > 1 && !mCore->mQueue[0].mIsAutoTimestamp) {
            // If entry[1] is timely, drop entry[0] (and repeat). We apply an
            // additional criterion here: we only drop the earlier buffer if our
            // desiredPresent falls within +/- 1 second of the expected present.
            // Otherwise, bogus desiredPresent times (e.g., 0 or a small
            // relative timestamp), which normally mean "ignore the timestamp
            // and acquire immediately", would cause us to drop frames.
            //
            // We may want to add an additional criterion: don't drop the
            // earlier buffer if entry[1]'s fence hasn't signaled yet.
            const BufferItem& bufferItem(mCore->mQueue[1]);
            nsecs_t desiredPresent = bufferItem.mTimestamp;
            if (desiredPresent < expectedPresent - MAX_REASONABLE_NSEC ||
                    desiredPresent > expectedPresent) {
                // This buffer is set to display in the near future, or
                // desiredPresent is garbage. Either way we don't want to drop
                // the previous buffer just to get this on the screen sooner.
                BQ_LOGV("acquireBuffer: nodrop desire=%" PRId64 " expect=%"
                        PRId64 " (%" PRId64 ") now=%" PRId64,
                        desiredPresent, expectedPresent,
                        desiredPresent - expectedPresent,
                        systemTime(CLOCK_MONOTONIC));
                break;
            }

            BQ_LOGV("acquireBuffer: drop desire=%" PRId64 " expect=%" PRId64
                    " size=%zu",
                    desiredPresent, expectedPresent, mCore->mQueue.size());
            if (mCore->stillTracking(front)) {
                // Front buffer is still in mSlots, so mark the slot as free
                mSlots[front->mSlot].mBufferState = BufferSlot::FREE;
            }
            mCore->mQueue.erase(front);
            front = mCore->mQueue.begin();
        }

        // See if the front buffer is due
        nsecs_t desiredPresent = front->mTimestamp;
        if (desiredPresent > expectedPresent &&
                desiredPresent < expectedPresent + MAX_REASONABLE_NSEC) {
            BQ_LOGV("acquireBuffer: defer desire=%" PRId64 " expect=%" PRId64
                    " (%" PRId64 ") now=%" PRId64,
                    desiredPresent, expectedPresent,
                    desiredPresent - expectedPresent,
                    systemTime(CLOCK_MONOTONIC));
            return PRESENT_LATER;
        }

        BQ_LOGV("acquireBuffer: accept desire=%" PRId64 " expect=%" PRId64 " "
                "(%" PRId64 ") now=%" PRId64, desiredPresent, expectedPresent,
                desiredPresent - expectedPresent,
                systemTime(CLOCK_MONOTONIC));
    }

    int slot = front->mSlot;
    *outBuffer = *front;
    ATRACE_BUFFER_INDEX(slot);

    BQ_LOGV("acquireBuffer: acquiring { slot=%d/%" PRIu64 " buffer=%p }",
            slot, front->mFrameNumber, front->mGraphicBuffer->handle);
    // If the front buffer is still being tracked, update its slot state
    if (mCore->stillTracking(front)) {
        mSlots[slot].mAcquireCalled = true;
        mSlots[slot].mNeedsCleanupOnRelease = false;
        mSlots[slot].mBufferState = BufferSlot::ACQUIRED;
        mSlots[slot].mFence = Fence::NO_FENCE;
    }

    // If the buffer has previously been acquired by the consumer, set
    // mGraphicBuffer to NULL to avoid unnecessarily remapping this buffer
    // on the consumer side
    if (outBuffer->mAcquireCalled) {
        outBuffer->mGraphicBuffer = NULL;
    }

    mCore->mQueue.erase(front);

    // We might have freed a slot while dropping old buffers, or the producer
    // may be blocked waiting for the number of buffers in the queue to
    // decrease.
    mCore->mDequeueCondition.broadcast();

    ATRACE_INT(mCore->mConsumerName.string(), mCore->mQueue.size());

    return NO_ERROR;
}

其实就是从mCore->mQueue 队列中取出第一个构造好的buffer。

同理如此分析releaseBufferLocked 函数。

回过头看一下 bindTextureImageLocked函数 : 作用就是将新的缓冲区绑定到GL纹理,OpenGL 相关了。

status_t GLConsumer::bindTextureImageLocked() {
        ............

        glEGLImageTargetTexture2DOES(mTexTarget, (GLeglImageOES)image);

        ..........
    return doGLFenceWaitLocked();

}

 

Region 了解

对于我们桌面上的图像,他是按照Layer 一层一层的铺上的,若是Layer 的Z值比较到,那么他就越在其他Layer的上层。

对于个每一个Layer 都有透明度的概念:

①、opaque:不透明,如果这个layer的某个区域设置的是不透明,那么这个Layer层的下面的Layer 就不会被看见。

②、transparent : 全透明,可以完全看见下面层的Layer。

③、translucent : 半透明,还是可以看见下面层的Layer。

在程序中,通过Region 结构体来表述透明度。

Region  由一系列的Rect(矩形)组成,这些矩形从上到下,从左到右排列出来,并且各个矩形的Y轴坐标相同(对于Y轴坐标相同的矩形X轴无交叉)或者无交叉。

Span :一组Rect ,Y轴一样,X轴无交叉。

Region定义的文件:frameworks\native\include\ui\Region.h ,里面有一个 Vector<Rect> mStorage; 成员变量。mStorage的最后一项表示边界

  1. 如果Region只是一个简单的矩形区域,则mStorage只包含一个Rect类型的元素。
  2. 如果Region中包含多个矩形区域,则mStorage只包含多个Rect类型的元素+最后元素(这块区域的边界)。

 

 

 

3、 signalRefresh();

void SurfaceFlinger::signalRefresh() {
    mEventQueue.refresh();
}

导致 case MessageQueue::REFRESH:下的 handleMessageRefresh();被调用。

void SurfaceFlinger::handleMessageRefresh() {
    ATRACE_CALL();
    preComposition(); //关键点1 合成前预处理
    rebuildLayerStacks();//关键点2 计算可见区域,主要依据:z-order大的覆盖有重叠区域z-order小的
    //关键点3 下面几个方法都是页面合成相关
    setUpHWComposer();
    doDebugFlashRegions();
    doComposition();//关键点4 合成所有层的图像, 经过这一步后,就显示新的内容了
    postComposition();//合成之后的工作
}

handleMessageRefresh

在handleMessageRefresh 函数里面,做的主要的工作是:

①计算各个Layer的显示区域

②合成并且显示,可以通过OpenGL的方式把每个layer的可视区域在一个内存里面描述出来;也可以通过硬件 HWComposer合成出来。

 

 ① preComposition():

处理一些标志位。

② rebuildLayerStacks():

显然rebuildLayerStacks()函数就是来处理各个Layer的显示区域。

在分析之前需要明确个基本概念:

  1. dirtyRegion:表示该区域是需要被刷新的。
  2. opaqueRegion:表示不透明区域。
  3. transparentRegion:表示完全透明区域。
  4. translucentRegion:表示半透明区域。

rebuildLayerStacks主要是做两件事:

  1. 重建每个显示设备的可见layer对象的列表。layer按照Z序排列,但每个Layer都有 透明区、不透明区、半透明区即下面的Layer某些区域也是有机会显示的
  2. 对每个显示设备,先计算和显示设备相同的layerStack值的layer对象在显示设备上的可见区域,然后将可见区域和显示设备的窗口有交集的layer组成一个新的列表,最后把这个列表设置到显示设备对象中。
void SurfaceFlinger::rebuildLayerStacks() {
    // rebuild the visible layer list per screen
    if (CC_UNLIKELY(mVisibleRegionsDirty)) {
        ATRACE_CALL();
        mVisibleRegionsDirty = false;
        invalidateHwcGeometry();

        const LayerVector& layers(mDrawingState.layersSortedByZ);
        for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
            Region opaqueRegion;
            Region dirtyRegion;
            Vector< sp<Layer> > layersSortedByZ;
            const sp<DisplayDevice>& hw(mDisplays[dpy]);
            const Transform& tr(hw->getTransform());
            const Rect bounds(hw->getBounds());
            if (hw->canDraw()) {
                SurfaceFlinger::computeVisibleRegions(layers,
                        hw->getLayerStack(), dirtyRegion, opaqueRegion);//计算每个Layer的可见区域,确定设备需要重新绘制的区域

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

SurfaceFlinger::computeVisibleRegions()比较核心重要,他的作用是记录各个Layer 的可视区域、被遮盖区域,并记录在layer中,汇总dirtyRegion, opaqueRegion形参中,即总的dirtyRegion 区域和总的opaqueRegion。最后回到rebuildLayerStacks,把得到的这些信息set到hw 对象里面去,用于接下来的合成。

先浏览一下computeVisibleRegions 函数吧:

void SurfaceFlinger::computeVisibleRegions(
        const LayerVector& currentLayers, uint32_t layerStack,
        Region& outDirtyRegion, Region& outOpaqueRegion)
{
    Region aboveOpaqueLayers;//当前层之上累计的不透明区域
    Region aboveCoveredLayers;//当前层之上累计的被覆盖区域,不透明+半透明
    Region dirty;
    outDirtyRegion.clear();总值
 
    size_t i = currentLayers.size();//最上层layer的索引
    while (i--) {//从Z轴 最上面的layer开始处理,由上到下
        const sp<Layer>& layer = currentLayers[i];
        const Layer::State& s(layer->getDrawingState());
        // 只计算和layerstack相同的layer,其他忽略
        if (s.layerStack != layerStack)
            continue;
 
        Region opaqueRegion;        //不透明区域
        Region visibleRegion;       //可见区域,不透明区域+半透明区域
        Region coveredRegion;       //覆盖区域,可见区域覆盖的地方
        Region transparentRegion;   //完全透明区域
        //stage1-start 得到当前Layer的原始可视区域 和 opaque区域
        // handle hidden surfaces by setting the visible region to empty
        if (CC_LIKELY(layer->isVisible())) {
            const bool translucent = !layer->isOpaque(s);
            Rect bounds(s.transform.transform(layer->computeBounds()));
            visibleRegion.set(bounds);
            if (!visibleRegion.isEmpty()) {
                // Remove the transparent area from the visible region
                if (translucent) {//计算透明区域
                    const Transform tr(s.transform);
                    if (tr.transformed()) {
                        if (tr.preserveRects()) {
                            // transform the transparent region
                            transparentRegion = tr.transform(s.activeTransparentRegion);
                        } else {
                            // transformation too complex, can't do the
                            // transparent region optimization.
                            transparentRegion.clear();
                        }
                    } else {
                        transparentRegion = s.activeTransparentRegion;
                    }
                }
 
                // 计算不透明区域
                const int32_t layerOrientation = s.transform.getOrientation();
                if (s.alpha==255 && !translucent &&
                        ((layerOrientation & Transform::ROT_INVALID) == false)) {
                    opaqueRegion = visibleRegion;
                }
            }
        }
        //stage1-end
 
        //当前Layer被遮盖区域:上层的覆盖区 和 layer所在区域的 交集
        coveredRegion = aboveCoveredLayers.intersect(visibleRegion);
 
        // 扩大覆盖区域,为下次循环、即下层计算做准备
        aboveCoveredLayers.orSelf(visibleRegion);
 
        //可见区域 = 抠掉上层的不透明区域
        visibleRegion.subtractSelf(aboveOpaqueLayers);
 
        // 计算需要重绘的区域
        if (layer->contentDirty) {
            //内容变了,重绘整个可见区域
            dirty = visibleRegion;
            //以前的看见区域也要加进来,因为以前的内容需要抹掉
            dirty.orSelf(layer->visibleRegion);
            layer->contentDirty = false;
        } else {
            //暴露区域 = 可见区域-被覆盖区域
            const Region newExposed = visibleRegion - coveredRegion;
            const Region oldVisibleRegion = layer->visibleRegion;
            const Region oldCoveredRegion = layer->coveredRegion;
            const Region oldExposed = oldVisibleRegion - oldCoveredRegion;
            dirty = (visibleRegion&oldCoveredRegion) | (newExposed-oldExposed);
        }
        
        //layer的重绘区域 = 抠掉上层的不透明区域
        dirty.subtractSelf(aboveOpaqueLayers);
 
        //累计每层需要重绘的区域
        outDirtyRegion.orSelf(dirty);
 
        //更新aboveOpaqueLayers,为下层layer绘制做准备
        aboveOpaqueLayers.orSelf(opaqueRegion);
 
        //设置layer对象的区域
        layer->setVisibleRegion(visibleRegion);
        layer->setCoveredRegion(coveredRegion);
        //设置可见的非透明区域
        layer->setVisibleNonTransparentRegion(
                visibleRegion.subtract(transparentRegion));
    }
 
    outOpaqueRegion = aboveOpaqueLayers;
}

总结下computeVisibleRegions的逻辑如下:

先计算每个layer在设备上的可见区域visibleRegion(不透明区域 + 半透明区域)。计算方法:整个Layer的区域-上层所有不透明区域aboveOpaqueLayers。而上层所有不透明区域的值 是一个逐层累积的过程,每层都把自己的不透明区域累加到aboveOpaqueLayers中。

每层的不透明区域的计算方法:如果layer的alpha值=255,并且layer的isOpaque = true,则本层的不透明区域 == layer所在区域。否则为0。这样一层层计算下来,就很容易得到每层的可见区域大小了。

这里以下图为例,解读下computeVisibleRegions这段逻辑:

假设有三个Layer,按照Z值从大到小,依次是Layer1->Layer2->Layer3,最后按照computeVisibleRegions的规则来合成Layer。有了这个图,看这段逻辑 便会更加直观。同时理解这段逻辑 最好的方法是将3个Layer带入到computeVisibleRegions方法中。

 

③setUpHWComposer

先不用管这个,这个这函数是硬件合成图像的(HWComposer),里面会有判断是否支持HWC,我们假设不支持,完全走egl ,gpu 合成,所以直接看doComposition函数。

④doComposition

在分析这个函数之前,先了解一下 DisplayDevice 类的作用。

先看一下两张图:

第一张图,表示我们的应用程序,获取surface,向surface请求buffer,这个buffer是android匿名内存里面分配出来的,这些buffer被surface这边的成员变量mSlots 管理着,当应用这边调用unlockAndPost 函数,提交已经绘制图像buffer以后,layer会通知surfaceflinger进程去处理新添加的buffer。surfaceflinger 经过文章前面一些流程处理后,就会把合成的buffer,提交给framebuffer,framebuffer是硬件分配的buffer,他们他们也是被surface类管理着,那么DisplayDevice的作用是啥呢?DisplayDevice类似于我们的应用进程,管理的是帧他可以请求硬件dequeuebuffer、queuebuffer,即lock、unlock的过程。

  1. 应用端的Buffer是向Ashmem申请的;DisplayDevice端的Buffer是向FrameBuffer申请的
  2. 应用端的Buffer是用来填充的;DisplayDevice端的Buffer是用来推给Framebuffer 渲染的

看一下DisplayDevice的创建过程:

DisplayDevice的创建过程在SurfaceFlinger::init()里面:

void SurfaceFlinger::init() {
    //...
    // initialize our non-virtual displays
    for (size_t i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {
        DisplayDevice::DisplayType type((DisplayDevice::DisplayType)i);
        // set-up the displays that are already connected
        if (mHwc->isConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) {
            // All non-virtual displays are currently considered secure.
            bool isSecure = true;
            createBuiltinDisplayLocked(type);
            wp<IBinder> token = mBuiltinDisplays[i];
            //BufferQueue相关
            sp<IGraphicBufferProducer> producer;
            sp<IGraphicBufferConsumer> consumer;
            BufferQueue::createBufferQueue(&producer, &consumer,
                    new GraphicBufferAlloc());
            //关键点1:FramebufferSurface创建,定位为 消费者身份
            sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i,
                    consumer);
            int32_t hwcId = allocateHwcDisplayId(type);
            //关键点2:DisplayDevice创建,定位为 生产者身份
            sp<DisplayDevice> hw = new DisplayDevice(this,
                    type, hwcId, mHwc->getFormat(hwcId), isSecure, token,
                    fbs, producer,
                    mRenderEngine->getEGLConfig());
            if (i > DisplayDevice::DISPLAY_PRIMARY) {
                hw->setPowerMode(HWC_POWER_MODE_NORMAL);
            }
            mDisplays.add(token, hw);
        }
    }
    //...
    // start boot animation
    startBootAnim();
}

FramebufferSurface构造函数实现如下:

FramebufferSurface::FramebufferSurface(HWComposer& hwc, int disp,
        const sp<IGraphicBufferConsumer>& consumer) :
    ConsumerBase(consumer),
    mDisplayType(disp),
    mCurrentBufferSlot(-1),
    mCurrentBuffer(0),
    mHwc(hwc)
{
    mName = "FramebufferSurface";
    mConsumer->setConsumerName(mName);
    /*这里设置了标志位GRALLOC_USAGE_HW_FB,借此参数分辨
    向Ashmem申请->APP;向Framebuffer申请->DisplayDevice
    */
    mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_FB |
                                       GRALLOC_USAGE_HW_RENDER |
                                       GRALLOC_USAGE_HW_COMPOSER);
    mConsumer->setDefaultBufferFormat(mHwc.getFormat(disp));
    mConsumer->setDefaultBufferSize(mHwc.getWidth(disp),  mHwc.getHeight(disp));
    mConsumer->setDefaultMaxBufferCount(NUM_FRAMEBUFFER_SURFACE_BUFFERS);
}

通过setConsumerUsageBits 函数,可以设置一个标志位,如果,表示向匿名共享内存申请buffer,为GRALLOC_USAGE_HW_FB,表示向显现驱动程序申请Framebuffer。

DisplayDevice的构造函数实现如下:

DisplayDevice::DisplayDevice(
        const sp<SurfaceFlinger>& flinger,
        DisplayType type,
        //...各种初始化
{
    //创建surface对象
    mNativeWindow = new Surface(producer, false);
    ANativeWindow* const window = mNativeWindow.get();
 
    //创建OpenGLES 使用的surface对象
    EGLSurface surface;
    EGLint w, h;
    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    if (config == EGL_NO_CONFIG) {
        config = RenderEngine::chooseEglConfig(display, format);
    }
    surface = eglCreateWindowSurface(display, config, window, NULL);
    eglQuerySurface(display, surface, EGL_WIDTH,  &mDisplayWidth);
    eglQuerySurface(display, surface, EGL_HEIGHT, &mDisplayHeight);
 
    if (mType >= DisplayDevice::DISPLAY_VIRTUAL)
        window->setSwapInterval(window, 0);//虚拟设备不支持 图像合成
 
    mConfig = config;
    mDisplay = display;
    mSurface = surface;
    mFormat  = format;
    mPageFlipCount = 0;
    mViewport.makeInvalid();
    mFrame.makeInvalid();
 
    //虚拟设备的屏幕 默认不关闭
    mPowerMode = (mType >= DisplayDevice::DISPLAY_VIRTUAL) ?
                  HWC_POWER_MODE_NORMAL : HWC_POWER_MODE_OFF;
 
    // Name the display.  The name will be replaced shortly if the display
    // was created with createDisplay().
    switch (mType) {
        case DISPLAY_PRIMARY:
            mDisplayName = "Built-in Screen";
            break;
        case DISPLAY_EXTERNAL:
            mDisplayName = "HDMI Screen";
            break;
        default:
            mDisplayName = "Virtual Screen";    // e.g. Overlay #n
            break;
    }
 
    // initialize the display orientation transform.
    setProjection(DisplayState::eOrientationDefault, mViewport, mFrame);
}

该构造函数主要是 创建了Surface,也就是一个NativeWindow。

这里看下 surface的构造函数,代码如下:

Surface::Surface(
        const sp<IGraphicBufferProducer>& bufferProducer,
        bool controlledByApp)
    : mGraphicBufferProducer(bufferProducer)
{
    // Initialize the ANativeWindow function pointers.
    ANativeWindow::setSwapInterval  = hook_setSwapInterval;
    ANativeWindow::dequeueBuffer    = hook_dequeueBuffer;
    ANativeWindow::cancelBuffer     = hook_cancelBuffer;
    ANativeWindow::queueBuffer      = hook_queueBuffer;
    ANativeWindow::query            = hook_query;
    ANativeWindow::perform          = hook_perform;
    //...
}

这里对其中的一个hook_queueBuffer进行分析,代码如下:

int Surface::hook_queueBuffer(ANativeWindow* window,
        ANativeWindowBuffer* buffer, int fenceFd) {
    Surface* c = getSelf(window);
    return c->queueBuffer(buffer, fenceFd);
}

最后是调用回了Surface的queueBuffer方法,其他几个hook方法也是类似的。即NativeWindow 和Surface访问的方法是一样的。

同时通过上面的分析得出Buffer的流程:Surface->BufferQueue->FramebufferSurface->HWComposer->Gralloc->显示设备Framebuffer.

 

 

最后在看一下doComposition 的函数处理内容:

这个UML图中,我们看出来在doComposeSurfaces函数里面最后会调用 layer->draw(hw, clip)进而开始调用OpenGL的接口开始绘制合成图像了。完了之后,回到doDisplayComposition函数,调用hw->swapBuffers(getHwComposer()),进行framebuffer的切换,即把准备好的framebuffer和正在显示器上显示的buffer进行交换,显示器就显示刚刚合成的新画面。

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值