SurfaceFlinger中Layer的合成 - 安卓R

1 等待任意Layer的buffer准备好

当BufferQueueLayer有新的buffer到来时,会调用之前在SurfaceFlinger中Layer的创建时注册的ContentsChangedListener的onFrameAvailable方法(frameworks/native/services/surfaceflinger/BufferQueueLayer.cpp):

void BufferQueueLayer::ContentsChangedListener::onFrameAvailable(const BufferItem& item) {
    Mutex::Autolock lock(mMutex);
    if (mBufferQueueLayer != nullptr) {
        mBufferQueueLayer->onFrameAvailable(item);
    }
}

直接调用了BufferQueueLayer的onFrameAvailable方法:

void BufferQueueLayer::onFrameAvailable(const BufferItem& item) {
    const int32_t layerId = getSequence();
    const uint64_t bufferId = item.mGraphicBuffer->getId();
    mFlinger->mFrameTracer->traceTimestamp(layerId, bufferId, item.mFrameNumber, systemTime(),
                                           FrameTracer::FrameEvent::QUEUE);
    mFlinger->mFrameTracer->traceFence(layerId, bufferId, item.mFrameNumber,
                                       std::make_shared<FenceTime>(item.mFence),
                                       FrameTracer::FrameEvent::ACQUIRE_FENCE);

    ATRACE_CALL();
    // Add this buffer from our internal queue tracker
    { // Autolock scope
        const nsecs_t presentTime = item.mIsAutoTimestamp ? 0 : item.mTimestamp;
        mFlinger->mScheduler->recordLayerHistory(this, presentTime,
                                                 LayerHistory::LayerUpdateType::Buffer);

        Mutex::Autolock lock(mQueueItemLock);
        // Reset the frame number tracker when we receive the first buffer after
        // a frame number reset
        if (item.mFrameNumber == 1) {
            mLastFrameNumberReceived = 0;
        }

        // Ensure that callbacks are handled in order
        while (item.mFrameNumber != mLastFrameNumberReceived + 1) {
            status_t result = mQueueItemCondition.waitRelative(mQueueItemLock, ms2ns(500));
            if (result != NO_ERROR) {
                ALOGE("[%s] Timed out waiting on callback", getDebugName());
                break;
            }
        }

        mQueueItems.push_back(item);
        mQueuedFrames++;

        // Wake up any pending callbacks
        mLastFrameNumberReceived = item.mFrameNumber;
        mQueueItemCondition.broadcast();
    }

    mFlinger->mInterceptor->saveBufferUpdate(layerId, item.mGraphicBuffer->getWidth(),
                                             item.mGraphicBuffer->getHeight(), item.mFrameNumber);

    mFlinger->signalLayerUpdate();
    mConsumer->onBufferAvailable(item);
}

最后调用了frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp的signalLayerUpdate方法:

void SurfaceFlinger::signalLayerUpdate() {
    mScheduler->resetIdleTimer();
    mPowerAdvisor.notifyDisplayUpdateImminent();
    mEventQueue->invalidate();
}

2 通过acquireBuffer方法锁定buffer

EventQueue的invalidate方法会导致SurfaceFlinger的onMessageInvalidate方法被调用:

void SurfaceFlinger::onMessageInvalidate(nsecs_t expectedVSyncTime) {
    ATRACE_CALL();

    const nsecs_t frameStart = systemTime();
    // calculate the expected present time once and use the cached
    // value throughout this frame to make sure all layers are
    // seeing this same value.
    if (expectedVSyncTime >= frameStart) {
        mExpectedPresentTime = expectedVSyncTime;
    } else {
        mExpectedPresentTime = mScheduler->getDispSyncExpectedPresentTime(frameStart);
    }

    const nsecs_t lastScheduledPresentTime = mScheduledPresentTime;
    mScheduledPresentTime = expectedVSyncTime;

    // When Backpressure propagation is enabled we want to give a small grace period
    // for the present fence to fire instead of just giving up on this frame to handle cases
    // where present fence is just about to get signaled.
    const int graceTimeForPresentFenceMs =
            (mPropagateBackpressure &&
             (mPropagateBackpressureClientComposition || !mHadClientComposition))
            ? 1
            : 0;

    // Pending frames may trigger backpressure propagation.
    const TracedOrdinal<bool> framePending = {"PrevFramePending",
                                              previousFramePending(graceTimeForPresentFenceMs)};

    // Frame missed counts for metrics tracking.
    // A frame is missed if the prior frame is still pending. If no longer pending,
    // then we still count the frame as missed if the predicted present time
    // was further in the past than when the fence actually fired.

    // Add some slop to correct for drift. This should generally be
    // smaller than a typical frame duration, but should not be so small
    // that it reports reasonable drift as a missed frame.
    DisplayStatInfo stats;
    mScheduler->getDisplayStatInfo(&stats);
    const nsecs_t frameMissedSlop = stats.vsyncPeriod / 2;
    const nsecs_t previousPresentTime = previousFramePresentTime();
    const TracedOrdinal<bool> frameMissed = {"PrevFrameMissed",
                                             framePending ||
                                                     (previousPresentTime >= 0 &&
                                                      (lastScheduledPresentTime <
                                                       previousPresentTime - frameMissedSlop))};
    const TracedOrdinal<bool> hwcFrameMissed = {"PrevHwcFrameMissed",
                                                mHadDeviceComposition && frameMissed};
    const TracedOrdinal<bool> gpuFrameMissed = {"PrevGpuFrameMissed",
                                                mHadClientComposition && frameMissed};

    if (frameMissed) {
        mFrameMissedCount++;
        mTimeStats->incrementMissedFrames();
        if (mMissedFrameJankCount == 0) {
            mMissedFrameJankStart = systemTime();
        }
        mMissedFrameJankCount++;
    }

    if (hwcFrameMissed) {
        mHwcFrameMissedCount++;
    }

    if (gpuFrameMissed) {
        mGpuFrameMissedCount++;
    }

    // If we are in the middle of a config change and the fence hasn't
    // fired yet just wait for the next invalidate
    if (mSetActiveConfigPending) {
        if (framePending) {
            mEventQueue->invalidate();
            return;
        }

        // We received the present fence from the HWC, so we assume it successfully updated
        // the config, hence we update SF.
        mSetActiveConfigPending = false;
        ON_MAIN_THREAD(setActiveConfigInternal());
    }

    if (framePending && mPropagateBackpressure) {
        if ((hwcFrameMissed && !gpuFrameMissed) || mPropagateBackpressureClientComposition) {
            signalLayerUpdate();
            return;
        }
    }

    // Our jank window is always at least 100ms since we missed a
    // frame...
    static constexpr nsecs_t kMinJankyDuration =
            std::chrono::duration_cast<std::chrono::nanoseconds>(100ms).count();
    // ...but if it's larger than 1s then we missed the trace cutoff.
    static constexpr nsecs_t kMaxJankyDuration =
            std::chrono::duration_cast<std::chrono::nanoseconds>(1s).count();
    nsecs_t jankDurationToUpload = -1;
    // If we're in a user build then don't push any atoms
    if (!mIsUserBuild && mMissedFrameJankCount > 0) {
        const auto display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked());
        // Only report jank when the display is on, as displays in DOZE
        // power mode may operate at a different frame rate than is
        // reported in their config, which causes noticeable (but less
        // severe) jank.
        if (display && display->getPowerMode() == hal::PowerMode::ON) {
            const nsecs_t currentTime = systemTime();
            const nsecs_t jankDuration = currentTime - mMissedFrameJankStart;
            if (jankDuration > kMinJankyDuration && jankDuration < kMaxJankyDuration) {
                jankDurationToUpload = jankDuration;
            }

            // We either reported a jank event or we missed the trace
            // window, so clear counters here.
            if (jankDuration > kMinJankyDuration) {
                mMissedFrameJankCount = 0;
                mMissedFrameJankStart = 0;
            }
        }
    }

    if (mTracingEnabledChanged) {
        mTracingEnabled = mTracing.isEnabled();
        mTracingEnabledChanged = false;
    }

    bool refreshNeeded;
    {
        ConditionalLockGuard<std::mutex> lock(mTracingLock, mTracingEnabled);

        refreshNeeded = handleMessageTransaction();
        refreshNeeded |= handleMessageInvalidate();
        if (mTracingEnabled) {
            mAddCompositionStateToTrace =
                    mTracing.flagIsSetLocked(SurfaceTracing::TRACE_COMPOSITION);
            if (mVisibleRegionsDirty && !mAddCompositionStateToTrace) {
                mTracing.notifyLocked("visibleRegionsDirty");
            }
        }
    }

    // Layers need to get updated (in the previous line) before we can use them for
    // choosing the refresh rate.
    // Hold mStateLock as chooseRefreshRateForContent promotes wp<Layer> to sp<Layer>
    // and may eventually call to ~Layer() if it holds the last reference
    {
        Mutex::Autolock _l(mStateLock);
        mScheduler->chooseRefreshRateForContent();
    }

    ON_MAIN_THREAD(performSetActiveConfig());

    updateCursorAsync();
    updateInputFlinger();

    refreshNeeded |= mRepaintEverything;
    if (refreshNeeded && CC_LIKELY(mBootStage != BootStage::BOOTLOADER)) {
        mLastJankDuration = jankDurationToUpload;
        // Signal a refresh if a transaction modified the window state,
        // a new buffer was latched, or if HWC has requested a full
        // repaint
        if (mFrameStartTime <= 0) {
            // We should only use the time of the first invalidate
            // message that signals a refresh as the beginning of the
            // frame. Otherwise the real frame time will be
            // underestimated.
            mFrameStartTime = frameStart;
        }
        signalRefresh();
    }
}

其中调用了SurfaceFlinger的handleMessageInvalidate方法:

bool SurfaceFlinger::handleMessageInvalidate() {
    ATRACE_CALL();
    bool refreshNeeded = handlePageFlip();

    if (mVisibleRegionsDirty) {
        computeLayerBounds();
    }

    for (auto& layer : mLayersPendingRefresh) {
        Region visibleReg;
        visibleReg.set(layer->getScreenBounds());
        invalidateLayerStack(layer, visibleReg);
    }
    mLayersPendingRefresh.clear();
    return refreshNeeded;
}

调用了SurfaceFlinger的handlePageFlip方法:

bool SurfaceFlinger::handlePageFlip()
{
    ATRACE_CALL();
    ALOGV("handlePageFlip");

    nsecs_t latchTime = systemTime();

    bool visibleRegions = false;
    bool frameQueued = false;
    bool newDataLatched = false;

    const nsecs_t expectedPresentTime = mExpectedPresentTime.load();

    // 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.
    mDrawingState.traverse([&](Layer* layer) {
        if (layer->hasReadyFrame()) {
            frameQueued = true;
            if (layer->shouldPresentNow(expectedPresentTime)) {
                mLayersWithQueuedFrames.push_back(layer);
            } else {
                ATRACE_NAME("!layer->shouldPresentNow()");
                layer->useEmptyDamage();
            }
        } else {
            layer->useEmptyDamage();
        }
    });

    // The client can continue submitting buffers for offscreen layers, but they will not
    // be shown on screen. Therefore, we need to latch and release buffers of offscreen
    // layers to ensure dequeueBuffer doesn't block indefinitely.
    for (Layer* offscreenLayer : mOffscreenLayers) {
        offscreenLayer->traverse(LayerVector::StateSet::Drawing,
                                         [&](Layer* l) { l->latchAndReleaseBuffer(); });
    }

    if (!mLayersWithQueuedFrames.empty()) {
        // mStateLock is needed for latchBuffer as LayerRejecter::reject()
        // writes to Layer current state. See also b/119481871
        Mutex::Autolock lock(mStateLock);

        for (auto& layer : mLayersWithQueuedFrames) {
            if (layer->latchBuffer(visibleRegions, latchTime, expectedPresentTime)) {
                mLayersPendingRefresh.push_back(layer);
            }
            layer->useSurfaceDamage();
            if (layer->isBufferLatched()) {
                newDataLatched = true;
            }
        }
    }

    mVisibleRegionsDirty |= visibleRegions;

    // If we will need to wake up at some time in the future to deal with a
    // queued frame that shouldn't be displayed during this vsync period, wake
    // up during the next vsync period to check again.
    if (frameQueued && (mLayersWithQueuedFrames.empty() || !newDataLatched)) {
        signalLayerUpdate();
    }

    // enter boot animation on first buffer latch
    if (CC_UNLIKELY(mBootStage == BootStage::BOOTLOADER && newDataLatched)) {
        ALOGI("Enter boot animation");
        mBootStage = BootStage::BOOTANIMATION;
    }

    mDrawingState.traverse([&](Layer* layer) { layer->updateCloneBufferInfo(); });

    // Only continue with the refresh if there is actually new work to do
    return !mLayersWithQueuedFrames.empty() && newDataLatched;
}

对所有有准备好了的buffer的Layer调用了latchBuffer方法,具体是调用了frameworks/native/services/surfaceflinger/BufferLayer.cpp的latchBuffer方法:

bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime,
                              nsecs_t expectedPresentTime) {
    ATRACE_CALL();

    bool refreshRequired = latchSidebandStream(recomputeVisibleRegions);

    if (refreshRequired) {
        return refreshRequired;
    }

    if (!hasReadyFrame()) {
        return false;
    }

    // if we've already called updateTexImage() without going through
    // a composition step, we have to skip this layer at this point
    // because we cannot call updateTeximage() without a corresponding
    // compositionComplete() call.
    // we'll trigger an update in onPreComposition().
    if (mRefreshPending) {
        return false;
    }

    // If the head buffer's acquire fence hasn't signaled yet, return and
    // try again later
    if (!fenceHasSignaled()) {
        ATRACE_NAME("!fenceHasSignaled()");
        mFlinger->signalLayerUpdate();
        return false;
    }

    // Capture the old state of the layer for comparisons later
    const State& s(getDrawingState());
    const bool oldOpacity = isOpaque(s);

    BufferInfo oldBufferInfo = mBufferInfo;

    if (!allTransactionsSignaled(expectedPresentTime)) {
        mFlinger->setTransactionFlags(eTraversalNeeded);
        return false;
    }

    status_t err = updateTexImage(recomputeVisibleRegions, latchTime, expectedPresentTime);
    if (err != NO_ERROR) {
        return false;
    }

    err = updateActiveBuffer();
    if (err != NO_ERROR) {
        return false;
    }

    err = updateFrameNumber(latchTime);
    if (err != NO_ERROR) {
        return false;
    }

    gatherBufferInfo();

    mRefreshPending = true;
    if (oldBufferInfo.mBuffer == nullptr) {
        // the first time we receive a buffer, we need to trigger a
        // geometry invalidation.
        recomputeVisibleRegions = true;
    }

    if ((mBufferInfo.mCrop != oldBufferInfo.mCrop) ||
        (mBufferInfo.mTransform != oldBufferInfo.mTransform) ||
        (mBufferInfo.mScaleMode != oldBufferInfo.mScaleMode) ||
        (mBufferInfo.mTransformToDisplayInverse != oldBufferInfo.mTransformToDisplayInverse)) {
        recomputeVisibleRegions = true;
    }

    if (oldBufferInfo.mBuffer != nullptr) {
        uint32_t bufWidth = mBufferInfo.mBuffer->getWidth();
        uint32_t bufHeight = mBufferInfo.mBuffer->getHeight();
        if (bufWidth != uint32_t(oldBufferInfo.mBuffer->width) ||
            bufHeight != uint32_t(oldBufferInfo.mBuffer->height)) {
            recomputeVisibleRegions = true;
        }
    }

    if (oldOpacity != isOpaque(s)) {
        recomputeVisibleRegions = true;
    }

    // Remove any sync points corresponding to the buffer which was just
    // latched
    {
        Mutex::Autolock lock(mLocalSyncPointMutex);
        auto point = mLocalSyncPoints.begin();
        while (point != mLocalSyncPoints.end()) {
            if (!(*point)->frameIsAvailable() || !(*point)->transactionIsApplied()) {
                // This sync point must have been added since we started
                // latching. Don't drop it yet.
                ++point;
                continue;
            }

            if ((*point)->getFrameNumber() <= mCurrentFrameNumber) {
                std::stringstream ss;
                ss << "Dropping sync point " << (*point)->getFrameNumber();
                ATRACE_NAME(ss.str().c_str());
                point = mLocalSyncPoints.erase(point);
            } else {
                ++point;
            }
        }
    }

    return true;
}

其中调用了frameworks/native/services/surfaceflinger/BufferQueueLayer.cpp的updateTexImage方法:

status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime,
                                          nsecs_t expectedPresentTime) {
    // This boolean is used to make sure that SurfaceFlinger's shadow copy
    // of the buffer queue isn't modified when the buffer queue is returning
    // BufferItem's that weren't actually queued. This can happen in shared
    // buffer mode.
    bool queuedBuffer = false;
    const int32_t layerId = getSequence();
    LayerRejecter r(mDrawingState, getCurrentState(), recomputeVisibleRegions,
                    getProducerStickyTransform() != 0, mName, mOverrideScalingMode,
                    getTransformToDisplayInverse());

    if (isRemovedFromCurrentState()) {
        expectedPresentTime = 0;
    }

    // updateTexImage() below might drop the some buffers at the head of the queue if there is a
    // buffer behind them which is timely to be presented. However this buffer may not be signaled
    // yet. The code below makes sure that this wouldn't happen by setting maxFrameNumber to the
    // last buffer that was signaled.
    uint64_t lastSignaledFrameNumber = mLastFrameNumberReceived;
    {
        Mutex::Autolock lock(mQueueItemLock);
        for (int i = 0; i < mQueueItems.size(); i++) {
            bool fenceSignaled =
                    mQueueItems[i].mFenceTime->getSignalTime() != Fence::SIGNAL_TIME_PENDING;
            if (!fenceSignaled) {
                break;
            }
            lastSignaledFrameNumber = mQueueItems[i].mFrameNumber;
        }
    }
    const uint64_t maxFrameNumberToAcquire =
            std::min(mLastFrameNumberReceived.load(), lastSignaledFrameNumber);

    status_t updateResult = mConsumer->updateTexImage(&r, expectedPresentTime, &mAutoRefresh,
                                                      &queuedBuffer, maxFrameNumberToAcquire);
    if (updateResult == BufferQueue::PRESENT_LATER) {
        // Producer doesn't want buffer to be displayed yet.  Signal a
        // layer update so we check again at the next opportunity.
        mFlinger->signalLayerUpdate();
        return BAD_VALUE;
    } else if (updateResult == BufferLayerConsumer::BUFFER_REJECTED) {
        // If the buffer has been rejected, remove it from the shadow queue
        // and return early
        if (queuedBuffer) {
            Mutex::Autolock lock(mQueueItemLock);
            mConsumer->mergeSurfaceDamage(mQueueItems[0].mSurfaceDamage);
            mFlinger->mTimeStats->removeTimeRecord(layerId, mQueueItems[0].mFrameNumber);
            mQueueItems.removeAt(0);
            mQueuedFrames--;
        }
        return BAD_VALUE;
    } 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.
        if (queuedBuffer) {
            Mutex::Autolock lock(mQueueItemLock);
            mQueueItems.clear();
            mQueuedFrames = 0;
            mFlinger->mTimeStats->onDestroy(layerId);
            mFlinger->mFrameTracer->onDestroy(layerId);
        }

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

    if (queuedBuffer) {
        // Autolock scope
        auto currentFrameNumber = mConsumer->getFrameNumber();

        Mutex::Autolock lock(mQueueItemLock);

        // Remove any stale buffers that have been dropped during
        // updateTexImage
        while (mQueueItems[0].mFrameNumber != currentFrameNumber) {
            mConsumer->mergeSurfaceDamage(mQueueItems[0].mSurfaceDamage);
            mFlinger->mTimeStats->removeTimeRecord(layerId, mQueueItems[0].mFrameNumber);
            mQueueItems.removeAt(0);
            mQueuedFrames--;
        }

        uint64_t bufferID = mQueueItems[0].mGraphicBuffer->getId();
        mFlinger->mTimeStats->setLatchTime(layerId, currentFrameNumber, latchTime);
        mFlinger->mFrameTracer->traceTimestamp(layerId, bufferID, currentFrameNumber, latchTime,
                                               FrameTracer::FrameEvent::LATCH);

        mQueueItems.removeAt(0);
    }

    // Decrement the queued-frames count.  Signal another event if we
    // have more frames pending.
    if ((queuedBuffer && mQueuedFrames.fetch_sub(1) > 1) || mAutoRefresh) {
        mFlinger->signalLayerUpdate();
    }

    return NO_ERROR;
}

又调用了frameworks/native/services/surfaceflinger/BufferLayerConsumer.cpp的updateTexImage方法:

status_t BufferLayerConsumer::updateTexImage(BufferRejecter* rejecter, nsecs_t expectedPresentTime,
                                             bool* autoRefresh, bool* queuedBuffer,
                                             uint64_t maxFrameNumber) {
    ATRACE_CALL();
    BLC_LOGV("updateTexImage");
    Mutex::Autolock lock(mMutex);

    if (mAbandoned) {
        BLC_LOGE("updateTexImage: BufferLayerConsumer is abandoned!");
        return NO_INIT;
    }

    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.
    status_t err = acquireBufferLocked(&item, expectedPresentTime, 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 {
            BLC_LOGE("updateTexImage: acquire failed: %s (%d)", strerror(-err), err);
        }
        return err;
    }

    if (autoRefresh) {
        *autoRefresh = item.mAutoRefresh;
    }

    if (queuedBuffer) {
        *queuedBuffer = item.mQueuedBuffer;
    }

    // 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 slot = item.mSlot;
    if (rejecter && rejecter->reject(mSlots[slot].mGraphicBuffer, item)) {
        releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer);
        return BUFFER_REJECTED;
    }

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

    if (!mRE.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;
}

调用了BufferLayerConsumer的acquireBufferLocked方法:

status_t BufferLayerConsumer::acquireBufferLocked(BufferItem* item, nsecs_t presentWhen,
                                                  uint64_t maxFrameNumber) {
    status_t err = ConsumerBase::acquireBufferLocked(item, presentWhen, maxFrameNumber);
    if (err != NO_ERROR) {
        return err;
    }

    // If item->mGraphicBuffer is not null, this buffer has not been acquired
    // before, so we need to clean up old references.
    if (item->mGraphicBuffer != nullptr) {
        std::lock_guard<std::mutex> lock(mImagesMutex);
        if (mImages[item->mSlot] == nullptr || mImages[item->mSlot]->graphicBuffer() == nullptr ||
            mImages[item->mSlot]->graphicBuffer()->getId() != item->mGraphicBuffer->getId()) {
            mImages[item->mSlot] = std::make_shared<Image>(item->mGraphicBuffer, mRE);
        }
    }

    return NO_ERROR;
}

调用了frameworks/native/libs/gui/ConsumerBase.cpp的acquireBufferLocked方法:

status_t ConsumerBase::acquireBufferLocked(BufferItem *item,
        nsecs_t presentWhen, uint64_t maxFrameNumber) {
    if (mAbandoned) {
        CB_LOGE("acquireBufferLocked: ConsumerBase is abandoned!");
        return NO_INIT;
    }

    status_t err = mConsumer->acquireBuffer(item, presentWhen, maxFrameNumber);
    if (err != NO_ERROR) {
        return err;
    }

    if (item->mGraphicBuffer != nullptr) {
        if (mSlots[item->mSlot].mGraphicBuffer != nullptr) {
            freeBufferLocked(item->mSlot);
        }
        mSlots[item->mSlot].mGraphicBuffer = item->mGraphicBuffer;
    }

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

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

    return OK;
}

这里的mConsumer就是BufferQueue的消费者IGraphicBufferConsumer,通过调用其acquireBuffer方法锁定了一个buffer。

SurfaceFlinger的onMessageInvalidate方法最后还调用了SurfaceFlinger的signalRefresh方法:

void SurfaceFlinger::signalRefresh() {
    mRefreshPending = true;
    mEventQueue->refresh();
}

3 合成所有Layer的buffer上交给屏幕

EventQueue的refresh方法会导致SurfaceFlinger的onMessageRefresh方法被调用:

void SurfaceFlinger::onMessageRefresh() {
    ATRACE_CALL();

    mRefreshPending = false;

    compositionengine::CompositionRefreshArgs refreshArgs;
    const auto& displays = ON_MAIN_THREAD(mDisplays);
    refreshArgs.outputs.reserve(displays.size());
    for (const auto& [_, display] : displays) {
        refreshArgs.outputs.push_back(display->getCompositionDisplay());
    }
    mDrawingState.traverseInZOrder([&refreshArgs](Layer* layer) {
        if (auto layerFE = layer->getCompositionEngineLayerFE())
            refreshArgs.layers.push_back(layerFE);
    });
    refreshArgs.layersWithQueuedFrames.reserve(mLayersWithQueuedFrames.size());
    for (sp<Layer> layer : mLayersWithQueuedFrames) {
        if (auto layerFE = layer->getCompositionEngineLayerFE())
            refreshArgs.layersWithQueuedFrames.push_back(layerFE);
    }

    refreshArgs.repaintEverything = mRepaintEverything.exchange(false);
    refreshArgs.outputColorSetting = useColorManagement
            ? mDisplayColorSetting
            : compositionengine::OutputColorSetting::kUnmanaged;
    refreshArgs.colorSpaceAgnosticDataspace = mColorSpaceAgnosticDataspace;
    refreshArgs.forceOutputColorMode = mForceColorMode;

    refreshArgs.updatingOutputGeometryThisFrame = mVisibleRegionsDirty;
    refreshArgs.updatingGeometryThisFrame = mGeometryInvalid || mVisibleRegionsDirty;
    refreshArgs.blursAreExpensive = mBlursAreExpensive;
    refreshArgs.internalDisplayRotationFlags = DisplayDevice::getPrimaryDisplayRotationFlags();

    if (CC_UNLIKELY(mDrawingState.colorMatrixChanged)) {
        refreshArgs.colorTransformMatrix = mDrawingState.colorMatrix;
        mDrawingState.colorMatrixChanged = false;
    }

    refreshArgs.devOptForceClientComposition = mDebugDisableHWC || mDebugRegion;

    if (mDebugRegion != 0) {
        refreshArgs.devOptFlashDirtyRegionsDelay =
                std::chrono::milliseconds(mDebugRegion > 1 ? mDebugRegion : 0);
    }

    mGeometryInvalid = false;

    // Store the present time just before calling to the composition engine so we could notify
    // the scheduler.
    const auto presentTime = systemTime();

    mCompositionEngine->present(refreshArgs);
    mTimeStats->recordFrameDuration(mFrameStartTime, systemTime());
    // Reset the frame start time now that we've recorded this frame.
    mFrameStartTime = 0;

    mScheduler->onDisplayRefreshed(presentTime);

    postFrame();
    postComposition();

    const bool prevFrameHadDeviceComposition = mHadDeviceComposition;

    mHadClientComposition = std::any_of(displays.cbegin(), displays.cend(), [](const auto& pair) {
        const auto& state = pair.second->getCompositionDisplay()->getState();
        return state.usesClientComposition && !state.reusedClientComposition;
    });
    mHadDeviceComposition = std::any_of(displays.cbegin(), displays.cend(), [](const auto& pair) {
        const auto& state = pair.second->getCompositionDisplay()->getState();
        return state.usesDeviceComposition;
    });
    mReusedClientComposition =
            std::any_of(displays.cbegin(), displays.cend(), [](const auto& pair) {
                const auto& state = pair.second->getCompositionDisplay()->getState();
                return state.reusedClientComposition;
            });

    // Only report a strategy change if we move in and out of composition with hw overlays
    if (prevFrameHadDeviceComposition != mHadDeviceComposition) {
        mTimeStats->incrementCompositionStrategyChanges();
    }

    // TODO: b/160583065 Enable skip validation when SF caches all client composition layers
    mVSyncModulator->onRefreshed(mHadClientComposition || mReusedClientComposition);

    mLayersWithQueuedFrames.clear();
    if (mVisibleRegionsDirty) {
        mVisibleRegionsDirty = false;
        if (mTracingEnabled && mAddCompositionStateToTrace) {
            mTracing.notify("visibleRegionsDirty");
        }
    }

    if (mCompositionEngine->needsAnotherUpdate()) {
        signalLayerUpdate();
    }
}

首先创建了类型为CompositionRefreshArgs的变量refreshArgs用来准备进行合成的参数,注意refreshArgs.outputs是一个元素类型为Output的vector,其中保存了所有DisplayDevice通过getCompositionDisplay方法得到的成员变量mCompositionDisplay,其类型为Output的子类Display。然后调用了frameworks/native/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp的present方法:

void CompositionEngine::present(CompositionRefreshArgs& args) {
    ATRACE_CALL();
    ALOGV(__FUNCTION__);

    preComposition(args);

    {
        // latchedLayers is used to track the set of front-end layer state that
        // has been latched across all outputs for the prepare step, and is not
        // needed for anything else.
        LayerFESet latchedLayers;

        for (const auto& output : args.outputs) {
            output->prepare(args, latchedLayers);
        }
    }

    updateLayerStateFromFE(args);

    for (const auto& output : args.outputs) {
        output->present(args);
    }
}

对每个Output对象(记住实际类型为Display!)调用了present方法(frameworks/native/services/surfaceflinger/CompositionEngine/src/Output.cpp):

void Output::present(const compositionengine::CompositionRefreshArgs& refreshArgs) {
    ATRACE_CALL();
    ALOGV(__FUNCTION__);

    updateColorProfile(refreshArgs);
    updateAndWriteCompositionState(refreshArgs);
    setColorTransform(refreshArgs);
    beginFrame();
    prepareFrame();
    devOptRepaintFlash(refreshArgs);
    finishFrame(refreshArgs);
    postFramebuffer();
}

其中调用了Output的prepareFrame方法:

void Output::prepareFrame() {
    ATRACE_CALL();
    ALOGV(__FUNCTION__);

    const auto& outputState = getState();
    if (!outputState.isEnabled) {
        return;
    }

    chooseCompositionStrategy();

    mRenderSurface->prepareFrame(outputState.usesClientComposition,
                                 outputState.usesDeviceComposition);
}

首先调用了chooseCompositionStrategy方法,这个方法在Display类中重写了,因此调用的是Display的chooseCompositionStrategy方法(frameworks/native/services/surfaceflinger/CompositionEngine/src/Display.cpp):

void Display::chooseCompositionStrategy() {
    ATRACE_CALL();
    ALOGV(__FUNCTION__);

    // Default to the base settings -- client composition only.
    Output::chooseCompositionStrategy();

    // If we don't have a HWC display, then we are done
    if (!mId) {
        return;
    }

    // Get any composition changes requested by the HWC device, and apply them.
    std::optional<android::HWComposer::DeviceRequestedChanges> changes;
    auto& hwc = getCompositionEngine().getHwComposer();
    if (status_t result = hwc.getDeviceCompositionChanges(*mId, anyLayersRequireClientComposition(),
                                                          &changes);
        result != NO_ERROR) {
        ALOGE("chooseCompositionStrategy failed for %s: %d (%s)", getName().c_str(), result,
              strerror(-result));
        return;
    }
    if (changes) {
        applyChangedTypesToLayers(changes->changedTypes);
        applyDisplayRequests(changes->displayRequests);
        applyLayerRequestsToLayers(changes->layerRequests);
        applyClientTargetRequests(changes->clientTargetProperty);
    }

    // Determine what type of composition we are doing from the final state
    auto& state = editState();
    state.usesClientComposition = anyLayersRequireClientComposition();
    state.usesDeviceComposition = !allLayersRequireClientComposition();
}

bool Display::anyLayersRequireClientComposition() const {
    const auto layers = getOutputLayersOrderedByZ();
    return std::any_of(layers.begin(), layers.end(),
                       [](const auto& layer) { return layer->requiresClientComposition(); });
}

bool Display::allLayersRequireClientComposition() const {
    const auto layers = getOutputLayersOrderedByZ();
    return std::all_of(layers.begin(), layers.end(),
                       [](const auto& layer) { return layer->requiresClientComposition(); });
}

针对每个Layer,有两种合成方式:

  1. Client:使用gpu合成,例如有圆角的窗口

  2. Device:使用hwc合成

如果有Layer需要Client合成方式,那么mState.usesClientComposition被设为true,如果不是所有Layer都需要Client合成方式,那么mState.usesDeviceComposition被设为true。

Output的prepareFrame方法最后还调用了frameworks/native/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp的prepareFrame方法:

void RenderSurface::prepareFrame(bool usesClientComposition, bool usesDeviceComposition) {
    DisplaySurface::CompositionType compositionType;
    if (usesClientComposition && usesDeviceComposition) {
        compositionType = DisplaySurface::COMPOSITION_MIXED;
    } else if (usesClientComposition) {
        compositionType = DisplaySurface::COMPOSITION_GPU;
    } else if (usesDeviceComposition) {
        compositionType = DisplaySurface::COMPOSITION_HWC;
    } else {
        // Nothing to do -- when turning the screen off we get a frame like
        // this. Call it a HWC frame since we won't be doing any GPU work but
        // will do a prepare/set cycle.
        compositionType = DisplaySurface::COMPOSITION_HWC;
    }

    if (status_t result = mDisplaySurface->prepareFrame(compositionType); result != NO_ERROR) {
        ALOGE("updateCompositionType failed for %s: %d (%s)", mDisplay.getName().c_str(), result,
              strerror(-result));
    }
}

针对整个屏幕合成,又分为三种合成方式:

  1. MIXED:既有Layer需要hwc合成又有Layer需要gpu合成

  2. GPU:所有Layer都需要gpu合成

  3. HWC:没有Layer需要gpu合成

回到Output的present方法在调用了prepareFrame方法决定合成方式后,后面还调用了Output的finishFrame方法:

void Display::finishFrame(const compositionengine::CompositionRefreshArgs& refreshArgs) {
    // We only need to actually compose the display if:
    // 1) It is being handled by hardware composer, which may need this to
    //    keep its virtual display state machine in sync, or
    // 2) There is work to be done (the dirty region isn't empty)
    if (!mId) {
        if (getDirtyRegion(refreshArgs.repaintEverything).isEmpty()) {
            ALOGV("Skipping display composition");
            return;
        }
    }

    impl::Output::finishFrame(refreshArgs);
}

void Output::finishFrame(const compositionengine::CompositionRefreshArgs& refreshArgs) {
    ATRACE_CALL();
    ALOGV(__FUNCTION__);

    if (!getState().isEnabled) {
        return;
    }

    // Repaint the framebuffer (if needed), getting the optional fence for when
    // the composition completes.
    auto optReadyFence = composeSurfaces(Region::INVALID_REGION, refreshArgs);
    if (!optReadyFence) {
        return;
    }

    // swap buffers (presentation)
    mRenderSurface->queueBuffer(std::move(*optReadyFence));
}

又调用了Output的composeSurfaces方法:

std::optional<base::unique_fd> Output::composeSurfaces(
        const Region& debugRegion, const compositionengine::CompositionRefreshArgs& refreshArgs) {
    ATRACE_CALL();
    ALOGV(__FUNCTION__);

    const auto& outputState = getState();
    OutputCompositionState& outputCompositionState = editState();
    const TracedOrdinal<bool> hasClientComposition = {"hasClientComposition",
                                                      outputState.usesClientComposition};

    auto& renderEngine = getCompositionEngine().getRenderEngine();
    const bool supportsProtectedContent = renderEngine.supportsProtectedContent();

    // If we the display is secure, protected content support is enabled, and at
    // least one layer has protected content, we need to use a secure back
    // buffer.
    if (outputState.isSecure && supportsProtectedContent) {
        auto layers = getOutputLayersOrderedByZ();
        bool needsProtected = std::any_of(layers.begin(), layers.end(), [](auto* layer) {
            return layer->getLayerFE().getCompositionState()->hasProtectedContent;
        });
        if (needsProtected != renderEngine.isProtected()) {
            renderEngine.useProtectedContext(needsProtected);
        }
        if (needsProtected != mRenderSurface->isProtected() &&
            needsProtected == renderEngine.isProtected()) {
            mRenderSurface->setProtected(needsProtected);
        }
    } else if (!outputState.isSecure && renderEngine.isProtected()) {
        renderEngine.useProtectedContext(false);
    }

    base::unique_fd fd;
    sp<GraphicBuffer> buf;

    // If we aren't doing client composition on this output, but do have a
    // flipClientTarget request for this frame on this output, we still need to
    // dequeue a buffer.
    if (hasClientComposition || outputState.flipClientTarget) {
        buf = mRenderSurface->dequeueBuffer(&fd);
        if (buf == nullptr) {
            ALOGW("Dequeuing buffer for display [%s] failed, bailing out of "
                  "client composition for this frame",
                  mName.c_str());
            return {};
        }
    }

    base::unique_fd readyFence;
    if (!hasClientComposition) {
        setExpensiveRenderingExpected(false);
        return readyFence;
    }

    ALOGV("hasClientComposition");

    renderengine::DisplaySettings clientCompositionDisplay;
    clientCompositionDisplay.physicalDisplay = outputState.destinationClip;
    clientCompositionDisplay.clip = outputState.sourceClip;
    clientCompositionDisplay.orientation = outputState.orientation;
    clientCompositionDisplay.outputDataspace = mDisplayColorProfile->hasWideColorGamut()
            ? outputState.dataspace
            : ui::Dataspace::UNKNOWN;
    clientCompositionDisplay.maxLuminance =
            mDisplayColorProfile->getHdrCapabilities().getDesiredMaxLuminance();

    // Compute the global color transform matrix.
    if (!outputState.usesDeviceComposition && !getSkipColorTransform()) {
        clientCompositionDisplay.colorTransform = outputState.colorTransformMatrix;
    }

    // Note: Updated by generateClientCompositionRequests
    clientCompositionDisplay.clearRegion = Region::INVALID_REGION;

    // Generate the client composition requests for the layers on this output.
    std::vector<LayerFE::LayerSettings> clientCompositionLayers =
            generateClientCompositionRequests(supportsProtectedContent,
                                              clientCompositionDisplay.clearRegion,
                                              clientCompositionDisplay.outputDataspace);
    appendRegionFlashRequests(debugRegion, clientCompositionLayers);

    // Check if the client composition requests were rendered into the provided graphic buffer. If
    // so, we can reuse the buffer and avoid client composition.
    if (mClientCompositionRequestCache) {
        if (mClientCompositionRequestCache->exists(buf->getId(), clientCompositionDisplay,
                                                   clientCompositionLayers)) {
            outputCompositionState.reusedClientComposition = true;
            setExpensiveRenderingExpected(false);
            return readyFence;
        }
        mClientCompositionRequestCache->add(buf->getId(), clientCompositionDisplay,
                                            clientCompositionLayers);
    }

    // We boost GPU frequency here because there will be color spaces conversion
    // or complex GPU shaders and it's expensive. We boost the GPU frequency so that
    // GPU composition can finish in time. We must reset GPU frequency afterwards,
    // because high frequency consumes extra battery.
    const bool expensiveBlurs =
            refreshArgs.blursAreExpensive && mLayerRequestingBackgroundBlur != nullptr;
    const bool expensiveRenderingExpected =
            clientCompositionDisplay.outputDataspace == ui::Dataspace::DISPLAY_P3 || expensiveBlurs;
    if (expensiveRenderingExpected) {
        setExpensiveRenderingExpected(true);
    }

    std::vector<const renderengine::LayerSettings*> clientCompositionLayerPointers;
    clientCompositionLayerPointers.reserve(clientCompositionLayers.size());
    std::transform(clientCompositionLayers.begin(), clientCompositionLayers.end(),
                   std::back_inserter(clientCompositionLayerPointers),
                   [](LayerFE::LayerSettings& settings) -> renderengine::LayerSettings* {
                       return &settings;
                   });

    const nsecs_t renderEngineStart = systemTime();
    status_t status =
            renderEngine.drawLayers(clientCompositionDisplay, clientCompositionLayerPointers,
                                    buf->getNativeBuffer(), /*useFramebufferCache=*/true,
                                    std::move(fd), &readyFence);

    if (status != NO_ERROR && mClientCompositionRequestCache) {
        // If rendering was not successful, remove the request from the cache.
        mClientCompositionRequestCache->remove(buf->getId());
    }

    auto& timeStats = getCompositionEngine().getTimeStats();
    if (readyFence.get() < 0) {
        timeStats.recordRenderEngineDuration(renderEngineStart, systemTime());
    } else {
        timeStats.recordRenderEngineDuration(renderEngineStart,
                                             std::make_shared<FenceTime>(
                                                     new Fence(dup(readyFence.get()))));
    }

    return readyFence;
}

如果是gpu合成,则会调用RenderSurface的dequeueBuffer方法:

sp<GraphicBuffer> RenderSurface::dequeueBuffer(base::unique_fd* bufferFence) {
    ATRACE_CALL();
    int fd = -1;
    ANativeWindowBuffer* buffer = nullptr;

    status_t result = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buffer, &fd);

    if (result != NO_ERROR) {
        ALOGE("ANativeWindow::dequeueBuffer failed for display [%s] with error: %d",
              mDisplay.getName().c_str(), result);
        // Return fast here as we can't do much more - any rendering we do
        // now will just be wrong.
        return mGraphicBuffer;
    }

    ALOGW_IF(mGraphicBuffer != nullptr, "Clobbering a non-null pointer to a buffer [%p].",
             mGraphicBuffer->getNativeBuffer()->handle);
    mGraphicBuffer = GraphicBuffer::from(buffer);

    *bufferFence = base::unique_fd(fd);

    return mGraphicBuffer;
}

调用了mNativeWindow的dequeueBuffer方法拿到一个buffer,并将这个buffer赋值给RenderSurface.mGraphicBuffer,最后将这个buffer返回。在Output的composeSurfaces方法中,后面调用了frameworks/native/libs/renderengine/gl/GLESRenderEngine.cpp的drawLayers方法来进行gpu合成:

status_t GLESRenderEngine::drawLayers(const DisplaySettings& display,
                                      const std::vector<const LayerSettings*>& layers,
                                      ANativeWindowBuffer* const buffer,
                                      const bool useFramebufferCache, base::unique_fd&& bufferFence,
                                      base::unique_fd* drawFence) {
    ATRACE_CALL();
    if (layers.empty()) {
        ALOGV("Drawing empty layer stack");
        return NO_ERROR;
    }

    if (bufferFence.get() >= 0) {
        // Duplicate the fence for passing to waitFence.
        base::unique_fd bufferFenceDup(dup(bufferFence.get()));
        if (bufferFenceDup < 0 || !waitFence(std::move(bufferFenceDup))) {
            ATRACE_NAME("Waiting before draw");
            sync_wait(bufferFence.get(), -1);
        }
    }

    if (buffer == nullptr) {
        ALOGE("No output buffer provided. Aborting GPU composition.");
        return BAD_VALUE;
    }

    std::unique_ptr<BindNativeBufferAsFramebuffer> fbo;
    // Gathering layers that requested blur, we'll need them to decide when to render to an
    // offscreen buffer, and when to render to the native buffer.
    std::deque<const LayerSettings*> blurLayers;
    if (CC_LIKELY(mBlurFilter != nullptr)) {
        for (auto layer : layers) {
            if (layer->backgroundBlurRadius > 0) {
                blurLayers.push_back(layer);
            }
        }
    }
    const auto blurLayersSize = blurLayers.size();

    if (blurLayersSize == 0) {
        fbo = std::make_unique<BindNativeBufferAsFramebuffer>(*this, buffer, useFramebufferCache);
        if (fbo->getStatus() != NO_ERROR) {
            ALOGE("Failed to bind framebuffer! Aborting GPU composition for buffer (%p).",
                  buffer->handle);
            checkErrors();
            return fbo->getStatus();
        }
        setViewportAndProjection(display.physicalDisplay, display.clip);
    } else {
        setViewportAndProjection(display.physicalDisplay, display.clip);
        auto status =
                mBlurFilter->setAsDrawTarget(display, blurLayers.front()->backgroundBlurRadius);
        if (status != NO_ERROR) {
            ALOGE("Failed to prepare blur filter! Aborting GPU composition for buffer (%p).",
                  buffer->handle);
            checkErrors();
            return status;
        }
    }

    // clear the entire buffer, sometimes when we reuse buffers we'd persist
    // ghost images otherwise.
    // we also require a full transparent framebuffer for overlays. This is
    // probably not quite efficient on all GPUs, since we could filter out
    // opaque layers.
    clearWithColor(0.0, 0.0, 0.0, 0.0);

    setOutputDataSpace(display.outputDataspace);
    setDisplayMaxLuminance(display.maxLuminance);
    setDisplayColorTransform(display.colorTransform);

    const mat4 projectionMatrix =
            ui::Transform(display.orientation).asMatrix4() * mState.projectionMatrix;
    if (!display.clearRegion.isEmpty()) {
        glDisable(GL_BLEND);
        fillRegionWithColor(display.clearRegion, 0.0, 0.0, 0.0, 1.0);
    }

    Mesh mesh = Mesh::Builder()
                        .setPrimitive(Mesh::TRIANGLE_FAN)
                        .setVertices(4 /* count */, 2 /* size */)
                        .setTexCoords(2 /* size */)
                        .setCropCoords(2 /* size */)
                        .build();
    for (auto const layer : layers) {
        if (blurLayers.size() > 0 && blurLayers.front() == layer) {
            blurLayers.pop_front();

            auto status = mBlurFilter->prepare();
            if (status != NO_ERROR) {
                ALOGE("Failed to render blur effect! Aborting GPU composition for buffer (%p).",
                      buffer->handle);
                checkErrors("Can't render first blur pass");
                return status;
            }

            if (blurLayers.size() == 0) {
                // Done blurring, time to bind the native FBO and render our blur onto it.
                fbo = std::make_unique<BindNativeBufferAsFramebuffer>(*this, buffer,
                                                                      useFramebufferCache);
                status = fbo->getStatus();
                setViewportAndProjection(display.physicalDisplay, display.clip);
            } else {
                // There's still something else to blur, so let's keep rendering to our FBO
                // instead of to the display.
                status = mBlurFilter->setAsDrawTarget(display,
                                                      blurLayers.front()->backgroundBlurRadius);
            }
            if (status != NO_ERROR) {
                ALOGE("Failed to bind framebuffer! Aborting GPU composition for buffer (%p).",
                      buffer->handle);
                checkErrors("Can't bind native framebuffer");
                return status;
            }

            status = mBlurFilter->render(blurLayersSize > 1);
            if (status != NO_ERROR) {
                ALOGE("Failed to render blur effect! Aborting GPU composition for buffer (%p).",
                      buffer->handle);
                checkErrors("Can't render blur filter");
                return status;
            }
        }

        mState.maxMasteringLuminance = layer->source.buffer.maxMasteringLuminance;
        mState.maxContentLuminance = layer->source.buffer.maxContentLuminance;
        mState.projectionMatrix = projectionMatrix * layer->geometry.positionTransform;

        const FloatRect bounds = layer->geometry.boundaries;
        Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>());
        position[0] = vec2(bounds.left, bounds.top);
        position[1] = vec2(bounds.left, bounds.bottom);
        position[2] = vec2(bounds.right, bounds.bottom);
        position[3] = vec2(bounds.right, bounds.top);

        setupLayerCropping(*layer, mesh);
        setColorTransform(layer->colorTransform);

        bool usePremultipliedAlpha = true;
        bool disableTexture = true;
        bool isOpaque = false;
        if (layer->source.buffer.buffer != nullptr) {
            disableTexture = false;
            isOpaque = layer->source.buffer.isOpaque;

            sp<GraphicBuffer> gBuf = layer->source.buffer.buffer;
            bindExternalTextureBuffer(layer->source.buffer.textureName, gBuf,
                                      layer->source.buffer.fence);

            usePremultipliedAlpha = layer->source.buffer.usePremultipliedAlpha;
            Texture texture(Texture::TEXTURE_EXTERNAL, layer->source.buffer.textureName);
            mat4 texMatrix = layer->source.buffer.textureTransform;

            texture.setMatrix(texMatrix.asArray());
            texture.setFiltering(layer->source.buffer.useTextureFiltering);

            texture.setDimensions(gBuf->getWidth(), gBuf->getHeight());
            setSourceY410BT2020(layer->source.buffer.isY410BT2020);

            renderengine::Mesh::VertexArray<vec2> texCoords(mesh.getTexCoordArray<vec2>());
            texCoords[0] = vec2(0.0, 0.0);
            texCoords[1] = vec2(0.0, 1.0);
            texCoords[2] = vec2(1.0, 1.0);
            texCoords[3] = vec2(1.0, 0.0);
            setupLayerTexturing(texture);
        }

        const half3 solidColor = layer->source.solidColor;
        const half4 color = half4(solidColor.r, solidColor.g, solidColor.b, layer->alpha);
        // Buffer sources will have a black solid color ignored in the shader,
        // so in that scenario the solid color passed here is arbitrary.
        setupLayerBlending(usePremultipliedAlpha, isOpaque, disableTexture, color,
                           layer->geometry.roundedCornersRadius);
        if (layer->disableBlending) {
            glDisable(GL_BLEND);
        }
        setSourceDataSpace(layer->sourceDataspace);

        if (layer->shadow.length > 0.0f) {
            handleShadow(layer->geometry.boundaries, layer->geometry.roundedCornersRadius,
                         layer->shadow);
        }
        // We only want to do a special handling for rounded corners when having rounded corners
        // is the only reason it needs to turn on blending, otherwise, we handle it like the
        // usual way since it needs to turn on blending anyway.
        else if (layer->geometry.roundedCornersRadius > 0.0 && color.a >= 1.0f && isOpaque) {
            handleRoundedCorners(display, *layer, mesh);
        } else {
            drawMesh(mesh);
        }

        // Cleanup if there's a buffer source
        if (layer->source.buffer.buffer != nullptr) {
            disableBlending();
            setSourceY410BT2020(false);
            disableTexturing();
        }
    }

    if (drawFence != nullptr) {
        *drawFence = flush();
    }
    // If flush failed or we don't support native fences, we need to force the
    // gl command stream to be executed.
    if (drawFence == nullptr || drawFence->get() < 0) {
        bool success = finish();
        if (!success) {
            ALOGE("Failed to flush RenderEngine commands");
            checkErrors();
            // Chances are, something illegal happened (either the caller passed
            // us bad parameters, or we messed up our shader generation).
            return INVALID_OPERATION;
        }
        mLastDrawFence = nullptr;
    } else {
        // The caller takes ownership of drawFence, so we need to duplicate the
        // fd here.
        mLastDrawFence = new Fence(dup(drawFence->get()));
    }
    mPriorResourcesCleaned = false;

    checkErrors();
    return NO_ERROR;
}

使用OpenGL将Layer的图像作为Texture绘制出来,绘制的图像输出到这个buffer中。

回到Output的finishFrame方法最后还调用了RenderSurface的queueBuffer方法:

void RenderSurface::queueBuffer(base::unique_fd readyFence) {
    auto& state = mDisplay.getState();

    if (state.usesClientComposition || state.flipClientTarget) {
        // hasFlipClientTargetRequest could return true even if we haven't
        // dequeued a buffer before. Try dequeueing one if we don't have a
        // buffer ready.
        if (mGraphicBuffer == nullptr) {
            ALOGI("Attempting to queue a client composited buffer without one "
                  "previously dequeued for display [%s]. Attempting to dequeue "
                  "a scratch buffer now",
                  mDisplay.getName().c_str());
            // We shouldn't deadlock here, since mGraphicBuffer == nullptr only
            // after a successful call to queueBuffer, or if dequeueBuffer has
            // never been called.
            base::unique_fd unused;
            dequeueBuffer(&unused);
        }

        if (mGraphicBuffer == nullptr) {
            ALOGE("No buffer is ready for display [%s]", mDisplay.getName().c_str());
        } else {
            status_t result =
                    mNativeWindow->queueBuffer(mNativeWindow.get(),
                                               mGraphicBuffer->getNativeBuffer(), dup(readyFence));
            if (result != NO_ERROR) {
                ALOGE("Error when queueing buffer for display [%s]: %d", mDisplay.getName().c_str(),
                      result);
                // We risk blocking on dequeueBuffer if the primary display failed
                // to queue up its buffer, so crash here.
                if (!mDisplay.isVirtual()) {
                    LOG_ALWAYS_FATAL("ANativeWindow::queueBuffer failed with error: %d", result);
                } else {
                    mNativeWindow->cancelBuffer(mNativeWindow.get(),
                                                mGraphicBuffer->getNativeBuffer(), dup(readyFence));
                }
            }

            mGraphicBuffer = nullptr;
        }
    }

    status_t result = mDisplaySurface->advanceFrame();
    if (result != NO_ERROR) {
        ALOGE("[%s] failed pushing new frame to HWC: %d", mDisplay.getName().c_str(), result);
    }
}

如果有需要gpu合成的Layer,则调用mNativeWindow的queueBuffer方法将刚刚绘制好了的mGraphicBuffer提交。至此gpu合成就完成了,接下来调用DisplaySurface的advanceFrame方法将这一帧交给hwc。

SurfaceFlinger的onMessageRefresh方法后面还调用了SurfaceFlinger的postComposition方法:

void SurfaceFlinger::postComposition()
{
    ATRACE_CALL();
    ALOGV("postComposition");

    nsecs_t dequeueReadyTime = systemTime();
    for (auto& layer : mLayersWithQueuedFrames) {
        layer->releasePendingBuffer(dequeueReadyTime);
    }

    const auto* display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked()).get();

    getBE().mGlCompositionDoneTimeline.updateSignalTimes();
    std::shared_ptr<FenceTime> glCompositionDoneFenceTime;
    if (display && display->getCompositionDisplay()->getState().usesClientComposition) {
        glCompositionDoneFenceTime =
                std::make_shared<FenceTime>(display->getCompositionDisplay()
                                                    ->getRenderSurface()
                                                    ->getClientTargetAcquireFence());
        getBE().mGlCompositionDoneTimeline.push(glCompositionDoneFenceTime);
    } else {
        glCompositionDoneFenceTime = FenceTime::NO_FENCE;
    }

    getBE().mDisplayTimeline.updateSignalTimes();
    mPreviousPresentFences[1] = mPreviousPresentFences[0];
    mPreviousPresentFences[0] =
            display ? getHwComposer().getPresentFence(*display->getId()) : Fence::NO_FENCE;
    auto presentFenceTime = std::make_shared<FenceTime>(mPreviousPresentFences[0]);
    getBE().mDisplayTimeline.push(presentFenceTime);

    DisplayStatInfo stats;
    mScheduler->getDisplayStatInfo(&stats);

    // We use the CompositionEngine::getLastFrameRefreshTimestamp() which might
    // be sampled a little later than when we started doing work for this frame,
    // but that should be okay since updateCompositorTiming has snapping logic.
    updateCompositorTiming(stats, mCompositionEngine->getLastFrameRefreshTimestamp(),
                           presentFenceTime);
    CompositorTiming compositorTiming;
    {
        std::lock_guard<std::mutex> lock(getBE().mCompositorTimingLock);
        compositorTiming = getBE().mCompositorTiming;
    }

    mDrawingState.traverse([&](Layer* layer) {
        const bool frameLatched = layer->onPostComposition(display, glCompositionDoneFenceTime,
                                                           presentFenceTime, compositorTiming);
        if (frameLatched) {
            recordBufferingStats(layer->getName(), layer->getOccupancyHistory(false));
        }
    });

    mTransactionCompletedThread.addPresentFence(mPreviousPresentFences[0]);
    mTransactionCompletedThread.sendCallbacks();

    if (display && display->isPrimary() && display->getPowerMode() == hal::PowerMode::ON &&
        presentFenceTime->isValid()) {
        mScheduler->addPresentFence(presentFenceTime);
    }

    const bool isDisplayConnected = display && getHwComposer().isConnected(*display->getId());

    if (!hasSyncFramework) {
        if (isDisplayConnected && display->isPoweredOn()) {
            mScheduler->enableHardwareVsync();
        }
    }

    if (mAnimCompositionPending) {
        mAnimCompositionPending = false;

        if (presentFenceTime->isValid()) {
            mAnimFrameTracker.setActualPresentFence(
                    std::move(presentFenceTime));
        } else if (isDisplayConnected) {
            // The HWC doesn't support present fences, so use the refresh
            // timestamp instead.
            const nsecs_t presentTime = getHwComposer().getRefreshTimestamp(*display->getId());
            mAnimFrameTracker.setActualPresentTime(presentTime);
        }
        mAnimFrameTracker.advanceFrame();
    }

    mTimeStats->incrementTotalFrames();
    if (mHadClientComposition) {
        mTimeStats->incrementClientCompositionFrames();
    }

    if (mReusedClientComposition) {
        mTimeStats->incrementClientCompositionReusedFrames();
    }

    mTimeStats->setPresentFenceGlobal(presentFenceTime);

    const size_t sfConnections = mScheduler->getEventThreadConnectionCount(mSfConnectionHandle);
    const size_t appConnections = mScheduler->getEventThreadConnectionCount(mAppConnectionHandle);
    mTimeStats->recordDisplayEventConnectionCount(sfConnections + appConnections);

    if (mLastJankDuration > 0) {
        ATRACE_NAME("Jank detected");
        const int32_t jankyDurationMillis = mLastJankDuration / (1000 * 1000);
        android::util::stats_write(android::util::DISPLAY_JANK_REPORTED, jankyDurationMillis,
                                   mMissedFrameJankCount);
        mLastJankDuration = -1;
    }

    if (isDisplayConnected && !display->isPoweredOn()) {
        return;
    }

    nsecs_t currentTime = systemTime();
    if (mHasPoweredOff) {
        mHasPoweredOff = false;
    } else {
        nsecs_t elapsedTime = currentTime - getBE().mLastSwapTime;
        size_t numPeriods = static_cast<size_t>(elapsedTime / stats.vsyncPeriod);
        if (numPeriods < SurfaceFlingerBE::NUM_BUCKETS - 1) {
            getBE().mFrameBuckets[numPeriods] += elapsedTime;
        } else {
            getBE().mFrameBuckets[SurfaceFlingerBE::NUM_BUCKETS - 1] += elapsedTime;
        }
        getBE().mTotalTime += elapsedTime;
    }
    getBE().mLastSwapTime = currentTime;

    // Cleanup any outstanding resources due to rendering a prior frame.
    getRenderEngine().cleanupPostRender();

    {
        std::lock_guard lock(mTexturePoolMutex);
        if (mTexturePool.size() < mTexturePoolSize) {
            const size_t refillCount = mTexturePoolSize - mTexturePool.size();
            const size_t offset = mTexturePool.size();
            mTexturePool.resize(mTexturePoolSize);
            getRenderEngine().genTextures(refillCount, mTexturePool.data() + offset);
            ATRACE_INT("TexturePoolSize", mTexturePool.size());
        } else if (mTexturePool.size() > mTexturePoolSize) {
            const size_t deleteCount = mTexturePool.size() - mTexturePoolSize;
            const size_t offset = mTexturePoolSize;
            getRenderEngine().deleteTextures(deleteCount, mTexturePool.data() + offset);
            mTexturePool.resize(mTexturePoolSize);
            ATRACE_INT("TexturePoolSize", mTexturePool.size());
        }
    }

    if (mLumaSampling && mRegionSamplingThread) {
        mRegionSamplingThread->notifyNewContent();
    }

    // Even though ATRACE_INT64 already checks if tracing is enabled, it doesn't prevent the
    // side-effect of getTotalSize(), so we check that again here
    if (ATRACE_ENABLED()) {
        // getTotalSize returns the total number of buffers that were allocated by SurfaceFlinger
        ATRACE_INT64("Total Buffer Size", GraphicBufferAllocator::get().getTotalSize());
    }
}

这里对每个之前用了其buffer的BufferQueueLayer调用了releasePendingBuffer方法:

void BufferQueueLayer::releasePendingBuffer(nsecs_t dequeueReadyTime) {
    if (!mConsumer->releasePendingBuffer()) {
        return;
    }

    auto releaseFenceTime = std::make_shared<FenceTime>(mConsumer->getPrevFinalReleaseFence());
    mReleaseTimeline.updateSignalTimes();
    mReleaseTimeline.push(releaseFenceTime);

    Mutex::Autolock lock(mFrameEventHistoryMutex);
    if (mPreviousFrameNumber != 0) {
        mFrameEventHistory.addRelease(mPreviousFrameNumber, dequeueReadyTime,
                                      std::move(releaseFenceTime));
    }
}

调用了BufferLayerConsumer的releasePendingBuffer方法:

bool BufferLayerConsumer::releasePendingBuffer() {
    if (!mPendingRelease.isPending) {
        BLC_LOGV("Pending buffer already released");
        return false;
    }
    BLC_LOGV("Releasing pending buffer");
    Mutex::Autolock lock(mMutex);
    status_t result =
            releaseBufferLocked(mPendingRelease.currentTexture, mPendingRelease.graphicBuffer);
    if (result < NO_ERROR) {
        BLC_LOGE("releasePendingBuffer failed: %s (%d)", strerror(-result), result);
    }
    mPendingRelease = PendingRelease();
    return true;
}

调用了其父类ConsumerBase的releaseBufferLocked方法:

status_t ConsumerBase::releaseBufferLocked(
        int slot, const sp<GraphicBuffer> graphicBuffer,
        EGLDisplay display, EGLSyncKHR eglFence) {
    if (mAbandoned) {
        CB_LOGE("releaseBufferLocked: ConsumerBase is abandoned!");
        return NO_INIT;
    }
    // If consumer no longer tracks this graphicBuffer (we received a new
    // buffer on the same slot), the buffer producer is definitely no longer
    // tracking it.
    if (!stillTracking(slot, graphicBuffer)) {
        return OK;
    }

    CB_LOGV("releaseBufferLocked: slot=%d/%" PRIu64,
            slot, mSlots[slot].mFrameNumber);
    status_t err = mConsumer->releaseBuffer(slot, mSlots[slot].mFrameNumber,
            display, eglFence, mSlots[slot].mFence);
    if (err == IGraphicBufferConsumer::STALE_BUFFER_SLOT) {
        freeBufferLocked(slot);
    }

    mPrevFinalReleaseFence = mSlots[slot].mFence;
    mSlots[slot].mFence = Fence::NO_FENCE;

    return err;
}

其中mConsume是BufferQueue的消费者IGraphicBufferConsumer,调用其releaseBuffer方法可以将之前锁定的buffer释放。

总结一下这里的几个类之间的关系:

BufferQueueLayer封装BufferLayerConsumer,BufferLayerConsumer的父类ConsumerBase封装IGraphicBufferConsumer。

DisplayDevice封装Display,Display的父类Output封装RenderSurface,RenderSurface封装DisplaySurface,DisplaySurface有两个子类:FramebufferSurface和VirtualDisplaySurface。

CompositionRefreshArgs的成员变量outputs包括所有DisplayDevice中的Display。

SurfaceFlinger的成员变量mDisplays存着所有的DisplayDevice。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

SSSxCCC

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

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

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

打赏作者

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

抵扣说明:

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

余额充值