当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();
}
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();
}
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,有两种合成方式:
Client:使用gpu合成,例如有圆角的窗口
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));
}
}
针对整个屏幕合成,又分为三种合成方式:
MIXED:既有Layer需要hwc合成又有Layer需要gpu合成
GPU:所有Layer都需要gpu合成
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。