5.1 应用端绘制
应用端渲染线程绘制完成后,通过BufferQueueProducer.queueBuffer将绘制后的buffer 句柄传给SF 去合成。
具体流程:
BufferQueueProducer.queueBuffer
-> ConsumerBase::onFrameAvailable
-> BufferQueueLayer::onFrameAvailable
5.2 SurfaceFlinger 端合成
继续看下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
//将待合成BufferItem 放入容器mQueueItems
mQueueItems.push_back(item);
//这个变量会在SurfaceFlinger 收到invalidate 消息后用到,根据改值是否大于0 ,用于判断是否需要合成
mQueuedFrames++;
if (item.mGraphicBuffer != nullptr) {
ALOGE("onFrameAvailable = %s, %d ",getName().c_str(), item.mGraphicBuffer->getHeight());
}
// 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);
}
onFrameAvailable方法主要是:
- 记录待合成buffer
- 向SF申请合成
SF 合成主要是处理两个消息:
- Invalidate
- Refresh
- Invalidate 消息处理
当Vsync 到来时会先处理Invalidate消息:
a. SurfaceFlinger::handleMessageInvalidate()
handleMessageTransaction()
flushTransactionQueues() //system server 或应用端Transaction.apply在此处生效
commitTransaction() //mDrawingState = mCurrentState;
- mCurrentState 应用传来的layer 状态集合
- mDrawingState SF 待合成的layer 状态集合
b. 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;
//这里遍历所有layer 判断是否需要先在显示
if (layer->shouldPresentNow(expectedPresentTime)) {
mLayersWithQueuedFrames.push_back(layer);
} else {
ATRACE_NAME("!layer->shouldPresentNow()");
layer->useEmptyDamage();
}
} else {
layer->useEmptyDamage();
}
});
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;
}
}
}
- 遍历所有layer 将需要立即合成的layer 放入容器mLayersWithQueuedFrames
- 遍历待合成容器mLayersWithQueuedFrames,取出对应的buffer
继续看下是否立即合成条件:shouldPresentNow
frameworks/native/services/surfaceflinger/BufferQueueLayer.cpp
bool BufferQueueLayer::shouldPresentNow(nsecs_t expectedPresentTime) const {
if (getSidebandStreamChanged() || getAutoRefresh()) {
return true;
}
if (!hasFrameUpdate()) {
return false;
}
这里关键是hasFrameUpdate() 方法
bool BufferQueueLayer::hasFrameUpdate() const {
return mQueuedFrames > 0;
}
应用queueBuffer 后,buffer 还没有被acquire ,mQueuedFrames会大于0
上面遍历mDrawingState 取出待绘制layer,放入容器 mLayersWithQueuedFrames
遍历 mLayersWithQueuedFrames调用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;
}
status_t err = updateTexImage(recomputeVisibleRegions, latchTime, expectedPresentTime);
继续看updateTexImage
BufferQueueLayer::updateTexImage
-> BufferLayerConsumer::updateTexImage
status_t BufferLayerConsumer::updateTexImage(BufferRejecter* rejecter, nsecs_t expectedPresentTime,
bool* autoRefresh, bool* queuedBuffer,
uint64_t maxFrameNumber) {
ATRACE_CALL();
BLC_LOGV("upd ateTexImage");
Mutex::Autolock lock(mMutex);
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 (item.mGraphicBuffer != nullptr) {
ALOGE("lzh100 updateTexImage = %s, %d ",mLayer->getName().c_str(), item.mGraphicBuffer->getHeight());
}
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);
return err;
}
- acquireBufferLocked 获取应用端queue 的buffer
- updateAndReleaseLocked更新buffer相关信息,即BufferItem对象
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->graphicBuffer() != nullptr)
? mCurrentTextureBuffer->graphicBuffer()->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<Image> 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->graphicBuffer());
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->graphicBuffer();
pendingRelease->isPending = true;
}
}
// Update the BufferLayerConsumer state.
mCurrentTexture = slot;
mCurrentTextureBuffer = nextTextureBuffer;
将buffer 更新到mCurrentTextureBuffer,代表当前Layer对应的待合成buffer, 后面Layer ::getBuffer 返回的就是mCurrentTextureBuffer, 流程如下:
sp<GraphicBuffer> BufferLayer::getBuffer() const {
return mBufferInfo.mBuffer;
}
看下mBufferInfo.mBuffer如何赋值,上面acquireBuffer 后updateTexImage中会调用updateAndReleaseLocked,再调用到updateActiveBuffer更新Buffer,所以这里把待合成的buffer 赋值给mBufferInfo.mBuffer
status_t BufferQueueLayer::updateActiveBuffer() {
// update the active buffer
mPreviousBufferId = getCurrentBufferId();
mBufferInfo.mBuffer =
mConsumer->getCurrentBuffer(&mBufferInfo.mBufferSlot, &mBufferInfo.mFence);
if (mBufferInfo.mBuffer == nullptr) {
// this can only happen if the very first buffer was rejected.
return BAD_VALUE;
}
return NO_ERROR;
}
最终getBuffer其是就是mCurrentTextureBuffer
sp<GraphicBuffer> BufferLayerConsumer::getCurrentBuffer(int* outSlot, sp<Fence>* outFence) const {
return mCurrentTextureBuffer == nullptr ? nullptr : mCurrentTextureBuffer->graphicBuffer();
}
到目前为止通过acquireBuffer获取到应用绘制的buffer 并更新在了Layer中的mBufferInfo.mBuffer可以通过方法getBuffer() 获取buffer
c. 最后如果需要refresh 触发refresh,发送refresh消息的前提:
- 有Transaction更新
- 有buffer 更新
void SurfaceFlinger::onMessageInvalidate(nsecs_t expectedVSyncTime) {
... ...
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");
}
}
}
... ...
if (refreshNeeded && CC_LIKELY(mBootStage != BootStage::BOOTLOADER)) {
signalR efresh();
}
}
2. 后继续处理refresh 消息:
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);
}
});
...
mCompositionEngine->present(refreshArgs);
}
SurfaceFlinger::onMessageRefresh()
->CompositionEngine::present
->Output::prepare
->Output::rebuildLayerStacks
从 rebuildLayerStacks 就是要合成layer 的筛选过程,注意rebuildLayerStacks的数据来源也是mDrawingState
frameworks/native/services/surfaceflinger/CompositionEngine/src/Output.cpp
void Output::rebuildLayerStacks(const compositionengine::CompositionRefreshArgs& refreshArgs,
LayerFESet& layerFESet) {
ATRACE_CALL();
ALOGV(__FUNCTION__);
auto& outputState = editState();
// Do nothing if this output is not enabled or there is no need to perform this update
if (!outputState.isEnabled || CC_LIKELY(!refreshArgs.updatingOutputGeometryThisFrame)) {
return;
}
// Process the layers to determine visibility and coverage
compositionengine::Output::CoverageState coverage{layerFESet};
collectVisibleLayers(refreshArgs, coverage);
// Compute the resulting coverage for this output, and store it for later
const ui::Transform& tr = outputState.transform;
Region undefinedRegion{outputState.bounds};
undefinedRegion.subtractSelf(tr.transform(coverage.aboveOpaqueLayers));
outputState.undefinedRegion = undefinedRegion;
outputState.dirtyRegion.orSelf(coverage.dirtyRegion);
}
继续看collectVisibleLayers:
void Output::collectVisibleLayers(const compositionengine::CompositionRefreshArgs& refreshArgs,
compositionengine::Output::CoverageState& coverage) {
// Evaluate the layers from front to back to determine what is visible. This
// also incrementally calculates the coverage information for each layer as
// well as the entire output.
for (auto layer : reversed(refreshArgs.layers)) {
// Incrementally process the coverage for each layer
ensureOutputLayerIfVisible(layer, coverage);
// TODO(b/121291683): Stop early if the output is completely covered and
// no more layers could even be visible underneath the ones on top.
}
setReleasedLayers(refreshArgs);
finalizePendingOutputLayers();
// Generate a simple Z-order values to each visible output layer
uint32_t zOrder = 0;
for (auto* outputLayer : getOutputLayersOrderedByZ()) {
outputLayer->editState().z = zOrder++;
}
}
逆序遍历,也就是从上到下遍历,决定哪个layer 是可见的以及计算赃区:
void Output::ensureOutputLayerIfVisible(sp<compositionengine::LayerFE>& layerFE,
compositionengine::Output::CoverageState& coverage) {
// Only consider the layers on the given layer stack
//只计算当前display 的layer
if (!belongsInOutput(layerFE)) {
return;
}
... ...
/*
* shadowRegion: Region cast by the layer's shadow.
*/
Region shadowRegion;
const ui::Transform& tr = layerFEState->geomLayerTransform;
// Get the visible region
// TODO(b/121291683): Is it worth creating helper methods on LayerFEState
// for computations like this?
const Rect visibleRect(tr.transform(layerFEState->geomLayerBounds));
visibleRegion.set(visibleRect);
... ...
// compute the opaque region
const auto layerOrientation = tr.getOrientation();
if (layerFEState->isOpaque && ((layerOrientation & ui::Transform::ROT_INVALID) == 0)) {
// If we one of the simple category of transforms (0/90/180/270 rotation
// + any flip), then the opaque region is the layer's footprint.
// Otherwise we don't try and compute the opaque region since there may
// be errors at the edges, and we treat the entire layer as
// translucent.
opaqueRegion.set(visibleRect);
}
// Clip the covered region to the visible region
// aboveCoveredLayers计代表目前被覆盖的区域,用于遍历更低层级时可见区域去掉被覆盖的区域
//第一层时,aboveCoveredLayers为空,coveredRegion也是为空
coveredRegion = coverage.aboveCoveredLayers.intersect(visibleRegion);
// Update accumAboveCoveredLayers for next (lower) layer
//更新aboveCoveredLayers,该层之下的Layer都被该层Layer覆盖,所以这里和可见区域做一个或操纵,最下面的区域被覆盖的越大
coverage.aboveCoveredLayers.orSelf(visibleRegion);
// subtract the opaque region covered by the layers above us
//减去我们上面的图层覆盖的不透明区域
visibleRegion.subtractSelf(coverage.aboveOpaqueLayers);
if (visibleRegion.isEmpty()) {
return;
}
// Get coverage information for the layer as previously displayed,
// also taking over ownership from mOutputLayersorderedByZ.
auto prevOutputLayerIndex = findCurrentOutputLayerForLayer(layerFE);
auto prevOutputLayer =
prevOutputLayerIndex ? getOutputLayerOrderedByZByIndex(*prevOutputLayerIndex) : nullptr;
// Get coverage information for the layer as previously displayed
// TODO(b/121291683): Define kEmptyRegion as a constant in Region.h
const Region kEmptyRegion;
const Region& oldVisibleRegion =
prevOutputLayer ? prevOutputLayer->getState().visibleRegion : kEmptyRegion;
const Region& oldCoveredRegion =
prevOutputLayer ? prevOutputLayer->getState().coveredRegion : kEmptyRegion;
// compute this layer's dirty region
//开始计算脏区
Region dirty;
//contentDirty表示Layer的可见区域被修改了
if (layerFEState->contentDirty) {
// we need to invalidate the whole region
dirty = visibleRegion;
// as well, as the old visible region
dirty.orSelf(oldVisibleRegion);
//如果contentDirty没有被修改,开始计算暴露出来的区域 exposedRegion
} else {
/* compute the exposed region:
* the exposed region consists of two components:
* 1) what's VISIBLE now and was COVERED before
* 2) what's EXPOSED now less what was EXPOSED before
*
* note that (1) is conservative, we start with the whole visible region
* but only keep what used to be covered by something -- which mean it
* may have been exposed.
*
* (2) handles areas that were not covered by anything but got exposed
* because of a resize.
*
*/
//暴露区域包含两个部分:1是之前被覆盖了,但是先在可见的区域,
//第二个是处理没有被覆盖但是因为resize 导致的暴露
const Region newExposed = visibleRegion - coveredRegion;
const Region oldExposed = oldVisibleRegion - oldCoveredRegion;
dirty = (visibleRegion & oldCoveredRegion) | (newExposed - oldExposed);
}
//脏区就是被把暴露区域减去被覆盖区域
dirty.subtractSelf(coverage.aboveOpaqueLayers);
// accumulate to the screen dirty region
//更新屏幕脏区,保存在coverage
coverage.dirtyRegion.orSelf(dirty);
// Update accumAboveOpaqueLayers for next (lower) layer
coverage.aboveOpaqueLayers.orSelf(opaqueRegion);
// Compute the visible non-transparent region
Region visibleNonTransparentRegion = visibleRegion.subtract(transparentRegion);
// Perform the final check to see if this layer is visible on this output
// TODO(b/121291683): Why does this not use visibleRegion? (see outputSpaceVisibleRegion below)
const auto& outputState = getState();
Region drawRegion(outputState.transform.transform(visibleNonTransparentRegion));
drawRegion.andSelf(outputState.bounds);
if (drawRegion.isEmpty()) {
return;
}
Region visibleNonShadowRegion = visibleRegion.subtract(shadowRegion);
// The layer is visible. Either reuse the existing outputLayer if we have
// one, or create a new one if we do not.
//创建OutputLayer, 将可见layer存到mCurrentOutputLayersOrderedByZ、mPendingOutputLayersOrderedByZ
auto result = ensureOutputLayer(prevOutputLayerIndex, layerFE);
// Store the layer coverage information into the layer state as some of it
// is useful later.
auto& outputLayerState = result->editState();
outputLayerState.visibleRegion = visibleRegion;
outputLayerState.visibleNonTransparentRegion = visibleNonTransparentRegion;
outputLayerState.coveredRegion = coveredRegion;
outputLayerState.outputSpaceVisibleRegion =
outputState.transform.transform(visibleNonShadowRegion.intersect(outputState.viewport));
outputLayerState.shadowRegion = shadowRegion;
}
OutputLayer* ensureOutputLayer(std::optional<size_t> prevIndex,
const sp<LayerFE>& layerFE) {
auto outputLayer = (prevIndex && *prevIndex <= mCurrentOutputLayersOrderedByZ.size())
? std::move(mCurrentOutputLayersOrderedByZ[*prevIndex])
: BaseOutput::createOutputLayer(layerFE);
auto result = outputLayer.get();
mPendingOutputLayersOrderedByZ.emplace_back(std::move(outputLayer));
return result;
}
rebuildLayerStacks先计算layer 是否可见,创建OutputLayer再计算脏区最后把可见layer 保存到一个容器中mCurrentOutputLayersOrderedByZ/mPendingOutputLayersOrderedByZ
frameworks/native/services/surfaceflinger/CompositionEngine/src/Display.cpp
std::unique_ptr<compositionengine::OutputLayer> Display::createOutputLayer(
const sp<compositionengine::LayerFE>& layerFE) const {
auto result = impl::createOutputLayer(*this, layerFE);
if (result && mId) {
auto& hwc = getCompositionEngine().getHwComposer();
auto displayId = *mId;
// Note: For the moment we ensure it is safe to take a reference to the
// HWComposer implementation by destroying all the OutputLayers (and
// hence the HWC2::Layers they own) before setting a new HWComposer. See
// for example SurfaceFlinger::updateVrFlinger().
// TODO(b/121291683): Make this safer.
auto hwcLayer = std::shared_ptr<HWC2::Layer>(hwc.createLayer(displayId),
[&hwc, displayId](HWC2::Layer* layer) {
hwc.destroyLayer(displayId, layer);
});
ALOGE_IF(!hwcLayer, "Failed to create a HWC layer for a HWC supported display %s",
getName().c_str());
result->setHwcLayer(std::move(hwcLayer));
}
return result;
}
到现在为止计算出了待合成的layer ,封装为OutputLayer, 并创建了与之对应的hwc layer。继续看present逻辑:CompositionEngine::present
->Output::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();//1
devOptRepaintFlash(refreshArgs);
finishFrame(refreshArgs);//2
postFramebuffer();//3
}
- updateAndWriteCompositionState 通过 layer->writeStateToHWC, 再调用 Composer::setLayerBuffer将buffer传给底层,对应方法但是还没有真正显示
- prepareFrame 选择合成策略 device /client,如果device 合成直接通过 Composer::presentOrValidateDisplay 显示,如果没有显示成功或者client合成继续走 hwcDisplay->validate逻辑
- finishFrame 调用composeSurfaces 开始GPU处理layer 合成逻辑, GPU 合成后通过Composer::setClientTarget 将GPU合成后的buffer传给底层
- postFramebuffer 如果存在client 合成再次调用 hwcDisplay->present送显
到此,SurfaceFlinger 中的Invalidate 和Refresh 消息主要工作就完成了,流程图如下:
补充一点,SF dump中的hwc layer 就是打印的outputLayer
Display 0 HWC layers:
-----------------------------------------------------------------------------------------------------------------------------------------------
Layer name
Z | Window Type | Comp Type | Transform | Disp Frame (LTRB) | Source Crop (LTRB) | Frame Rate (Explicit) [Focused]
-----------------------------------------------------------------------------------------------------------------------------------------------
com.theme.wallpaper.WallpaperService#0
rel 0 | 2013 | CLIENT | 0 | 0 0 2880 1080 | 0.0 0.0 2880.0 1080.0 | [ ]
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
com.android.launcher3/com.android.launcher3.Launcher#0
rel 0 | 1 | CLIENT | 0 | 0 0 2880 1080 | 0.0 0.0 2880.0 1080.0 | [ ]
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#0
rel 0 | 2038 | CLIENT | 0 | 0 0 2880 96 | 0.0 0.0 2880.0 96.0 | [ ]
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Background for -SurfaceView - dock#0
rel -1 | 0 | CLIENT | 0 | 976 936 1904 1060 | 0.0 0.0 0.0 0.0 | [ ]
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
dock#0
rel 0 | 2059 | CLIENT | 0 | 976 920 1904 1080 | 0.0 0.0 928.0 160.0 | [ ]
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
从dump debug 可以判断layer 是否被可见性过滤掉了
frameworks/native/services/surfaceflinger/Layer.cpp
void Layer::miniDump(std::string& result, const DisplayDevice& display) const {
const auto outputLayer = findOutputLayerForDisplay(&display);
if (!outputLayer) {
return;
}
std::string name;
if (mName.length() > 77) {
5.3 实例分析
问题描述:地图应用由分屏到全屏时闪黑
我们先抓取perfetto 分析:
首先怀疑全屏尺寸没有设置到Layer,通过在Layer.cpp 中打log 发现全屏尺寸已经设置成功(1920):
2000-01-01 02:43:35.324 540 607 E Layer : setSize = SurfaceView - com.xxx.map.NaviActivity#0, 1920
已经设置给layer了,那么就怀疑应用没有用新的尺寸绘制,我们先看trace 中setLayer 之后的应用端绘制:
设置完1920 后只画了两帧, 我们继续看下SF 端acquireBffer 有没有收到应用的绘制buffer,
从上面时间点后SF 一直没有收到SurfaceView 的buffer 更新,直到空调界面退出,大概 5、6s 后SF 终于收到SurfaceView 重绘的buffer.
也就证明了前面的猜想,窗口大小改变后应用确实没有重绘,通过打log 的方式也可以证明应用没有queueBuffer
//设置尺寸
2000-01-01 02:43:35.324 540 607 E Layer : setSize = SurfaceView - NaviActivity#0, 1920
2000-01-01 02:43:35.324 540 607 E BufferQueueConsumer: [SurfaceView - NaviActivity#0](id:21c0000001a,api:0,p:-1,c:540) setDefaultBufferSize: width=1440 height=1920
//只有Activity 的queueBuffer 没有SurfaceView 的queueBuffer
2000-01-01 02:43:35.379 540 1115 E BufferQueueProducer: [NaviActivity#0](id:21c00000019,api:1,p:5204,c:540) queueBuffer: height=1920
2000-01-01 02:43:35.379 540 1115 E BufferQueueLayer: onFrameAvailable = NaviActivity#0, 1920
2000-01-01 02:43:35.408 540 540 E BufferLayerConsumer: updateTexImage = NaviActivity#0, 1920
2000-01-01 02:43:35.474 540 607 E BufferQueueProducer: [NaviActivity#0](id:21c00000019,api:1,p:5204,c:540) queueBuffer: height=1920
2000-01-01 02:43:35.474 540 607 E BufferQueueLayer: onFrameAvailable = NaviActivity#0, 1920
2000-01-01 02:43:35.541 540 540 E BufferLayerConsumer: updateTexImage = NaviActivity#0, 1920
//12 s 后SurfaceView 才queueBuffer
2000-01-01 02:43:47.125 540 2439 E BufferQueueProducer: [SurfaceView - NaviActivity#0](id:21c0000001a,api:1,p:5204,c:540) queueBuffer: height=1920
问题结论就是应用监听到大小变化要触发重绘。