wentao

记录多一点,懂得多一点

Android13 BufferQueueLayer OnFrameAvailable流程分析-CSDN博客

BufferQueueLayer的onFrameAvailable方法用于通知图像或视频帧已经可用并准备好显示,代码如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
//frameworks/native/services/surfaceflinger/BufferQueueLayer.cpp
sp<SurfaceFlinger> mFlinger;
sp<BufferLayerConsumer> mConsumer;
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;
 
 
        using LayerUpdateType = scheduler::LayerHistory::LayerUpdateType;
        mFlinger->mScheduler->recordLayerHistory(this, presentTime, 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;
            }
        }
 
 
        auto surfaceFrame = createSurfaceFrameForBuffer(mFrameTimelineInfo, systemTime(), mName);
 
 
        mQueueItems.push_back({item, surfaceFrame});
        mQueuedFrames++;
 
 
        // Wake up any pending callbacks
        mLastFrameNumberReceived = item.mFrameNumber;
        mQueueItemCondition.broadcast();
    }
 
 
    mFlinger->mInterceptor->saveBufferUpdate(layerId, item.mGraphicBuffer->getWidth(),
                                             item.mGraphicBuffer->getHeight(), item.mFrameNumber);
 
 
    mFlinger->onLayerUpdate();
    mConsumer->onBufferAvailable(item);
}

上面方法主要处理如下:

Android13 BufferQueueLayer OnLayerDisplayed流程分析-CSDN博客

BufferQueueLayer的onLayerDisplayed方法在BufferQueueLayer被显示时调用,代码如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
//frameworks/native/services/surfaceflinger/BufferQueueLayer.cpp
sp<SurfaceFlinger> mFlinger;
const std::unique_ptr<FrameTracer> mFrameTracer;
void BufferQueueLayer::onLayerDisplayed(ftl::SharedFuture<FenceResult> futureFenceResult) {
    const sp<Fence> releaseFence = futureFenceResult.get().value_or(Fence::NO_FENCE);
    mConsumer->setReleaseFence(releaseFence);
 
 
    // Prevent tracing the same release multiple times.
    if (mPreviousFrameNumber != mPreviousReleasedFrameNumber) {
        mFlinger->mFrameTracer->traceFence(getSequence(), mPreviousBufferId, mPreviousFrameNumber,
                                           std::make_shared<FenceTime>(releaseFence),
                                           FrameTracer::FrameEvent::RELEASE_FENCE);
        mPreviousReleasedFrameNumber = mPreviousFrameNumber;
    }
}

FrameTracer traceFence

调用FrameTracer的traceFence方法,用于分析和调试界面渲染的性能问题:

Android13 BufferQueueLayer UpdateTexImage流程分析-CSDN博客

BufferQueueLayer的updateTexImage方法用于将当前图形缓冲区的内容更新到纹理中,代码如下:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
//frameworks/native/services/surfaceflinger/BufferQueueLayer.cpp
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, getDrawingState(), recomputeVisibleRegions,
                    getProducerStickyTransform() != 0, mName,
                    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 (size_t i = 0; i < mQueueItems.size(); i++) {
            bool fenceSignaled =
                    mQueueItems[i].item.mFenceTime->getSignalTime() != Fence::SIGNAL_TIME_PENDING;
            if (!fenceSignaled) {
                break;
            }
            lastSignaledFrameNumber = mQueueItems[i].item.mFrameNumber;
        }
    }
    const uint64_t maxFrameNumberToAcquire =
            std::min(mLastFrameNumberReceived.load(), lastSignaledFrameNumber);
 
 
    bool autoRefresh;
    status_t updateResult = mConsumer->updateTexImage(&r, expectedPresentTime, &autoRefresh,
                                                      &queuedBuffer, maxFrameNumberToAcquire);
    mDrawingState.autoRefresh = autoRefresh;
    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.
 // Producer 不希望显示缓冲区。 发出图层更新的信号,以便我们在下次有机会时再次检查。
        mFlinger->onLayerUpdate(); // (692) SurfaceFlinger onLayerUpdate流程分析 
        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);
            if (mQueuedFrames > 0) {
                mConsumer->mergeSurfaceDamage(mQueueItems[0].item.mSurfaceDamage);
                mFlinger->mTimeStats->removeTimeRecord(layerId, mQueueItems[0].item.mFrameNumber);
                if (mQueueItems[0].surfaceFrame) {
                    addSurfaceFrameDroppedForBuffer(mQueueItems[0].surfaceFrame);
                }
                mQueueItems.erase(mQueueItems.begin());
                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);
            for (auto& [item, surfaceFrame] : mQueueItems) {
                if (surfaceFrame) {
                    addSurfaceFrameDroppedForBuffer(surfaceFrame);
                }
            }
            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;
    }
 
 
    bool more_frames_pending = false;
    if (queuedBuffer) {
        // Autolock scope
        auto currentFrameNumber = mConsumer->getFrameNumber();
 
 
        Mutex::Autolock lock(mQueueItemLock);
 
 
        // Remove any stale buffers that have been dropped during
        // updateTexImage
        while (mQueuedFrames > 0 && mQueueItems[0].item.mFrameNumber != currentFrameNumber) {
            mConsumer->mergeSurfaceDamage(mQueueItems[0].item.mSurfaceDamage);
            mFlinger->mTimeStats->removeTimeRecord(layerId, mQueueItems[0].item.mFrameNumber);
            if (mQueueItems[0].surfaceFrame) {
                addSurfaceFrameDroppedForBuffer(mQueueItems[0].surfaceFrame);
            }
            mQueueItems.erase(mQueueItems.begin());
            mQueuedFrames--;
        }
 
 
        uint64_t bufferID = mQueueItems[0].item.mGraphicBuffer->getId();
        mFlinger->mTimeStats->setLatchTime(layerId, currentFrameNumber, latchTime);
        mFlinger->mFrameTracer->traceTimestamp(layerId, bufferID, currentFrameNumber, latchTime,
                                               FrameTracer::FrameEvent::LATCH);
 
 
        if (mQueueItems[0].surfaceFrame) {
            addSurfaceFramePresentedForBuffer(mQueueItems[0].surfaceFrame,
                                              mQueueItems[0].item.mFenceTime->getSignalTime(),
                                              latchTime);
        }
        mQueueItems.erase(mQueueItems.begin());
        more_frames_pending = (mQueuedFrames.fetch_sub(1) > 1);
    }
 
 
    // Decrement the queued-frames count.  Signal another event if we
    // have more frames pending.
    //减少排队的帧计数。 如果我们有更多待处理的帧,则发出另一个事件的信号。
    if ((queuedBuffer && more_frames_pending) || mDrawingState.autoRefresh) {
        mFlinger->onLayerUpdate(); // (692) SurfaceFlinger onLayerUpdate流程分析 | 知识管理 - PingCode 
    }
 
 
    return NO_ERROR;
}

BufferLayerConsumer updateTexImage

调用BufferLayerConsumer的updateTexImage方法:

0%