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方法:

 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
//frameworks/native/surfaces/surfaceflienger/BufferLayerConsumer.cpp
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
    //我们在这里调用拒绝器,以防调用者有理由不接受此缓冲区, SurfaceFlinger 使用它来拒绝大小错误的缓冲区
    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;
    }
    return err;
}

上面方法的主要处理如下:

1、调用BufferLayerConsumer的acquireBufferLocked方法,从BufferQueue中获取一个可用的图像缓冲区。

2、调用BufferLayerConsumer的updateAndReleaseLocked方法,释放图像缓冲区。

下面分别进行分析:

BufferLayerConsumer acquireBufferLocked

调用BufferLayerConsumer的acquireBufferLocked方法,从BufferQueue中获取一个可用的图像缓冲区:

 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
//frameworks/native/services/surfaceflinger/BufferLayerConsumer.cpp
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]->getBuffer() == nullptr ||
            mImages[item->mSlot]->getBuffer()->getId() != item->mGraphicBuffer->getId()) {
            mImages[item->mSlot] = std::make_shared<
                    renderengine::impl::ExternalTexture>(item->mGraphicBuffer, mRE,
                                                         renderengine::impl::ExternalTexture::
                                                                 Usage::READABLE);
        }
    }
 
 
    return NO_ERROR;
}

ConsumerBase acquireBufferLocked

BufferLayerConsumer继承于ConsumerBase,调用ConsumerBase的acquireBufferLocked方法:

 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
//frameworks/native/libs/gui/ConsumerBase.cpp
sp<IGraphicBufferConsumer> mConsumer;
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(IGraphicBufferConsumer)的acquireBuffer方法,IGraphicBufferConsumer是一个接口,由BpGraphicBufferConsumer实现:

1
2
3
4
5
6
7
8
//frameworks/native/libs/gui/IGraphicBufferConsumer.cpp
class BpGraphicBufferConsumer : public SafeBpInterface<IGraphicBufferConsumer> {
    status_t acquireBuffer(BufferItem* buffer, nsecs_t presentWhen,
                           uint64_t maxFrameNumber) override {
        using Signature = decltype(&IGraphicBufferConsumer::acquireBuffer);
        return callRemote<Signature>(Tag::ACQUIRE_BUFFER, buffer, presentWhen, maxFrameNumber);
    }
}

调用callRemote方法进行远程调用,之后会运行BnGraphicBufferConsumer的onTransact方法:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
//frameworks/native/libs/gui/IGraphicBufferConsumer.cpp
status_t BnGraphicBufferConsumer::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
                                             uint32_t flags) {
    if (code < IBinder::FIRST_CALL_TRANSACTION || code > static_cast<uint32_t>(Tag::LAST)) {
        return BBinder::onTransact(code, data, reply, flags);
    }
    auto tag = static_cast<Tag>(code);
    switch (tag) {
        case Tag::ACQUIRE_BUFFER:
            return callLocal(data, reply, &IGraphicBufferConsumer::acquireBuffer);
        }
    }
}
BuffQueueConsumer acquireBuffer

BuffQueueConsumer继承于BnGraphicBufferConsumer,调用BnGraphicBufferConsumer的acquireBuffer方法:

Android13 BufferQueueConsumer acquireBuffer流程分析-CSDN博客

BufferLayerConsumer updateAndReleaseLocked

调用BufferLayerConsumer的updateAndReleaseLocked方法,释放图像缓冲区:

 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
//frameworks/native/services/surfaceflinger/BufferLayerConsumer.cpp
status_t BufferLayerConsumer::updateAndReleaseLocked(const BufferItem& item,
                                                     PendingRelease* pendingRelease) {
    status_t err = NO_ERROR;
 
 
    int slot = item.mSlot;
 
 
    BLC_LOGV("updateAndRelease: (slot=%d buf=%p) -> (slot=%d buf=%p)", mCurrentTexture,
             (mCurrentTextureBuffer != nullptr && mCurrentTextureBuffer->getBuffer() != nullptr)
                     ? mCurrentTextureBuffer->getBuffer()->handle
                     : 0,
             slot, mSlots[slot].mGraphicBuffer->handle);
 
 
    // Hang onto the pointer so that it isn't freed in the call to
    // releaseBufferLocked() if we're in shared buffer mode and both buffers are
    // the same.
 
 
    std::shared_ptr<renderengine::ExternalTexture> nextTextureBuffer;
    {
        std::lock_guard<std::mutex> lock(mImagesMutex);
        nextTextureBuffer = mImages[slot];
    }
 
 
    // release old buffer
    if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
        if (pendingRelease == nullptr) {
            status_t status =
                    releaseBufferLocked(mCurrentTexture, mCurrentTextureBuffer->getBuffer());
            if (status < NO_ERROR) {
                BLC_LOGE("updateAndRelease: failed to release buffer: %s (%d)", strerror(-status),
                         status);
                err = status;
                // keep going, with error raised [?]
            }
        } else {
            pendingRelease->currentTexture = mCurrentTexture;
            pendingRelease->graphicBuffer = mCurrentTextureBuffer->getBuffer();
            pendingRelease->isPending = true;
        }
    }
 
 
    // Update the BufferLayerConsumer state.
    mCurrentTexture = slot;
    mCurrentTextureBuffer = nextTextureBuffer;
    mCurrentCrop = item.mCrop;
    mCurrentTransform = item.mTransform;
    mCurrentScalingMode = item.mScalingMode;
    mCurrentTimestamp = item.mTimestamp;
    mCurrentDataSpace = static_cast<ui::Dataspace>(item.mDataSpace);
    mCurrentHdrMetadata = item.mHdrMetadata;
    mCurrentFence = item.mFence;
    mCurrentFenceTime = item.mFenceTime;
    mCurrentFrameNumber = item.mFrameNumber;
    mCurrentTransformToDisplayInverse = item.mTransformToDisplayInverse;
    mCurrentSurfaceDamage = item.mSurfaceDamage;
    mCurrentApi = item.mApi;
 
 
    computeCurrentTransformMatrixLocked();
 
 
    return err;
}

ConsumerBase releaseBufferLocked

BufferLayerConsumer继承于ConsumerBase,调用ConsumerBase的releaseBufferLocked方法:

 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
//frameworks/native/libs/gui/ConsumerBase.cpp
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;
}

调用mConsumer(IGraphicBufferConsumer)的releaseBuffer

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
//frameworks/native/include/gui/IGraphicBufferConsumer.h
using ReleaseBuffer = decltype(&IGraphicBufferConsumer::releaseHelper);
//frameworks/native/libs/gui/IGraphicBufferConsumer.cpp
status_t BnGraphicBufferConsumer::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
                                             uint32_t flags) {
    if (code < IBinder::FIRST_CALL_TRANSACTION || code > static_cast<uint32_t>(Tag::LAST)) {
        return BBinder::onTransact(code, data, reply, flags);
    }
    auto tag = static_cast<Tag>(code);
    switch (tag) {
        case Tag::RELEASE_BUFFER:
            return callLocal(data, reply, &IGraphicBufferConsumer::releaseHelper);
        }
    }
}

seBuffer方法,IGraphicBufferConsumer是一个接口,由BpGraphicBufferConsumer实现:

1
2
3
4
5
6
7
8
9
//frameworks/native/libs/gui/IGraphicBufferConsumer.cpp
class BpGraphicBufferConsumer : public SafeBpInterface<IGraphicBufferConsumer> {
    status_t releaseBuffer(int buf, uint64_t frameNumber,
                           EGLDisplay display __attribute__((unused)),
                           EGLSyncKHR fence __attribute__((unused)),
                           const sp<Fence>& releaseFence) override {
        return callRemote<ReleaseBuffer>(Tag::RELEASE_BUFFER, buf, frameNumber, releaseFence);
    }
}

调用callRemote方法进行远程调用,之后会运行BnGraphicBufferConsumer的onTransact方法:

BuffQueueConsumer releaseBuffer

BuffQueueConsumer继承于BnGraphicBufferConsumer,调用BnGraphicBufferConsumer的ReleaseBuffer 方法:

Android13 BufferQueueConsumer releaseBuffer流程分析-CSDN博客

0%