Android P 显示流程分析---界面刷新
Posted Give.Me.Five
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android P 显示流程分析---界面刷新相关的知识,希望对你有一定的参考价值。
上篇分析到SurfaceFlinger.signalRefresh()里会调用到SurfaceFlinger里的handleMessageRefresh(), 现在这里面开始涉及到图层合成了,这里面涉及的流程。
handleMessageRefresh()
void SurfaceFlinger::handleMessageRefresh()
mRefreshPending = false;
nsecs_t refreshStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
//合成图像前的准备工作,设置各种状态
preComposition(refreshStartTime);
//重建可见区域的所有图层
rebuildLayerStacks();
//启动硬件图像合成
setUpHWComposer();
//调试信息
doDebugFlashRegions();
doTracing("handleRefresh");
logLayerStats();
//合成处理
doComposition();
//更新状态与下次合成时间
postComposition(refreshStartTime);
上面重点的就是两块,一个setupHWComposer() 启动硬件图像合成, 另一个是doComposition()合成处理。
setUpHWComposer()
void SurfaceFlinger::setUpHWComposer()
...
if (CC_UNLIKELY(mGeometryInvalid))
mGeometryInvalid = false;
//遍历所有的显示设备
for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++)
sp<const DisplayDevice> displayDevice(mDisplays[dpy]);
const auto hwcId = displayDevice->getHwcDisplayId();
if (hwcId >= 0)
const Vector<sp<Layer>>& currentLayers(
displayDevice->getVisibleLayersSortedByZ());
//遍历当前显示设备的所有图层
for (size_t i = 0; i < currentLayers.size(); i++)
const auto& layer = currentLayers[i];
if (!layer->hasHwcLayer(hwcId))
//如果没有硬件图层,则创建一个硬件图层
if (!layer->createHwcLayer(getBE().mHwc.get(), hwcId))
layer->forceClientComposition(hwcId);
continue;
//设置图层大小,坐标
layer->setGeometry(displayDevice, i);
if (mDebugDisableHWC || mDebugRegion)
layer->forceClientComposition(hwcId);
// Set the per-frame data
//遍历所有显示屏
for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId)
auto& displayDevice = mDisplays[displayId];
const auto hwcId = displayDevice->getHwcDisplayId();
if (hwcId < 0)
continue;
//更新颜色变化
if (mDrawingState.colorMatrixChanged)
displayDevice->setColorTransform(mDrawingState.colorMatrix);
status_t result = getBE().mHwc->setColorTransform(hwcId, mDrawingState.colorMatrix);
ALOGE_IF(result != NO_ERROR, "Failed to set color transform on "
"display %zd: %d", displayId, result);
//遍历当前显示屏的所有图层
for (auto& layer : displayDevice->getVisibleLayersSortedByZ())
//设置数据存储格式
if (layer->isHdrY410())
layer->forceClientComposition(hwcId);
else if ((layer->getDataSpace() == Dataspace::BT2020_PQ ||
layer->getDataSpace() == Dataspace::BT2020_ITU_PQ) &&
!displayDevice->hasHDR10Support())
layer->forceClientComposition(hwcId);
else if ((layer->getDataSpace() == Dataspace::BT2020_HLG ||
layer->getDataSpace() == Dataspace::BT2020_ITU_HLG) &&
!displayDevice->hasHLGSupport())
layer->forceClientComposition(hwcId);
//设置图层合成类型
if (layer->getForceClientComposition(hwcId))
ALOGV("[%s] Requesting Client composition", layer->getName().string());
layer->setCompositionType(hwcId, HWC2::Composition::Client);
continue;
//图层的数据设置到显示器
layer->setPerFrameData(displayDevice);
//设置颜色模式
if (hasWideColorDisplay)
ColorMode colorMode;
Dataspace dataSpace;
RenderIntent renderIntent;
pickColorMode(displayDevice, &colorMode, &dataSpace, &renderIntent);
setActiveColorModeInternal(displayDevice, colorMode, dataSpace, renderIntent);
mDrawingState.colorMatrixChanged = false;
//遍历所有显示屏设备,做了prepareFrame
for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId)
auto& displayDevice = mDisplays[displayId];
if (!displayDevice->isDisplayOn())
continue;
status_t result = displayDevice->prepareFrame(*getBE().mHwc);
ALOGE_IF(result != NO_ERROR, "prepareFrame for display %zd failed:"
" %d (%s)", displayId, result, strerror(-result));
因为setUpHWComposer()里做的事情很多,我们一个一个来撸下:
按照我们《Android P 显示流程(一)—Display设备初始化过程分析》
后续最终会调用到HWC2On1Adapter里的createLayer的方法:
Error HWC2On1Adapter::Display::createLayer(hwc2_layer_t* outLayerId)
std::unique_lock<std::recursive_mutex> lock(mStateMutex);
//通过当前Display对象,创建一个新的layer对象,最后添加到mLayers 容器中
auto layer = *mLayers.emplace(std::make_shared<Layer>(*this));
mDevice.mLayers.emplace(std::make_pair(layer->getId(), layer));
*outLayerId = layer->getId();
ALOGV("[%" PRIu64 "] created layer %" PRIu64, mId, *outLayerId);
markGeometryChanged();
return Error::None;
-
layer->setGeometry(displayDevice, i)
设置图层大小和坐标位置,这个不是重点,我们就不往下分析了,后面更新颜色矩阵变化也直接跳过 -
后面有遍历显示屏的所有图层,设置数据存储格式也跳过不研究,来看看设置合成类型。
void Layer::setCompositionType(int32_t hwcId, HWC2::Composition type, bool callIntoHwc)
auto& hwcInfo = getBE().mHwcLayers[hwcId];
auto& hwcLayer = hwcInfo.layer;
//判读与目前此图层的合成类型是否一致,如果不一致,更改合成类型
if (hwcInfo.compositionType != type)
ALOGV(" actually setting");
hwcInfo.compositionType = type;
if (callIntoHwc)
auto error = hwcLayer->setCompositionType(type);
Error Layer::setCompositionType(Composition type)
auto intType = static_cast<Hwc2::IComposerClient::Composition>(type);
auto intError = mComposer.setLayerCompositionType(
mDisplayId, mId, intType);
return static_cast<Error>(intError);
//同之前分析的流程,最后会调用到HWC2On1Adapter里面
Error HWC2On1Adapter::Layer::setCompositionType(Composition type)
mCompositionType.setPending(type);
return Error::None;
这个设置图层的类型,那图层到底有哪些类型呢?
- Composition::Client
- Composition::Device
- Composition::SolidColor
- Composition::Cursor
- Composition::Sideband
上面这几种Composition 类型到底有什么区别呢,看看applyCompositionType:
void HWC2On1Adapter::Layer::applyCompositionType(hwc_layer_1_t& hwc1Layer,
bool applyAllState)
// HWC1 never supports color transforms or dataspaces and only sometimes
// supports plane alpha (depending on the version). These require us to drop
// some or all layers to client composition.
if (mHasUnsupportedDataspace || mHasUnsupportedPlaneAlpha ||
mDisplay.hasColorTransform())
hwc1Layer.compositionType = HWC_FRAMEBUFFER;
hwc1Layer.flags = HWC_SKIP_LAYER;
return;
if (applyAllState || mCompositionType.isDirty())
hwc1Layer.flags = 0;
switch (mCompositionType.getPendingValue())
case Composition::Client:
hwc1Layer.compositionType = HWC_FRAMEBUFFER;
hwc1Layer.flags |= HWC_SKIP_LAYER;
break;
case Composition::Device:
hwc1Layer.compositionType = HWC_FRAMEBUFFER;
break;
case Composition::SolidColor:
// In theory the following line should work, but since the HWC1
// version of SurfaceFlinger never used HWC_BACKGROUND, HWC1
// devices may not work correctly. To be on the safe side, we
// fall back to client composition.
//
// hwc1Layer.compositionType = HWC_BACKGROUND;
hwc1Layer.compositionType = HWC_FRAMEBUFFER;
hwc1Layer.flags |= HWC_SKIP_LAYER;
break;
case Composition::Cursor:
hwc1Layer.compositionType = HWC_FRAMEBUFFER;
if (mDisplay.getDevice().getHwc1MinorVersion() >= 4)
hwc1Layer.hints |= HWC_IS_CURSOR_LAYER;
break;
case Composition::Sideband:
if (mDisplay.getDevice().getHwc1MinorVersion() < 4)
hwc1Layer.compositionType = HWC_SIDEBAND;
else
hwc1Layer.compositionType = HWC_FRAMEBUFFER;
hwc1Layer.flags |= HWC_SKIP_LAYER;
break;
default:
hwc1Layer.compositionType = HWC_FRAMEBUFFER;
hwc1Layer.flags |= HWC_SKIP_LAYER;
break;
ALOGV("Layer %" PRIu64 " %s set to %d", mId,
to_string(mCompositionType.getPendingValue()).c_str(),
hwc1Layer.compositionType);
ALOGV_IF(hwc1Layer.flags & HWC_SKIP_LAYER, " and skipping");
mCompositionType.latch();
这几种虽然不一样,但对应的hwc1Layer.compositionType都是HWC_FRAMEBUFFER,实际上对应HAL层的实现没什么区别。
- 每个图层设置每帧的数据
layer->setPerFrameData(displayDevice)
但图层又分BufferLayer和ColorLayer,这两路图层有什么区别呢?
const sp<Client>& client,
uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
int32_t windowType, int32_t ownerUid, sp<IBinder>* handle,
sp<IGraphicBufferProducer>* gbp, sp<Layer>* parent)
switch (flags & ISurfaceComposerClient::eFXSurfaceMask)
case ISurfaceComposerClient::eFXSurfaceNormal:
result = createBufferLayer(client,
uniqueName, w, h, flags, format,
handle, gbp, &layer);
break;
case ISurfaceComposerClient::eFXSurfaceColor:
result = createColorLayer(client,
uniqueName, w, h, flags,
handle, &layer);
break;
default:
result = BAD_VALUE;
...
创建图层时,根据Flag 的不同来创建图层的,一种是纯色的,一种是普通数据显示的图层,这里我们一般指的是BufferLayer.
那继续看BufferLayer的setPerFrameData的函数:
void BufferLayer::setPerFrameData(const sp<const DisplayDevice>& displayDevice)
// Apply this display's projection's viewport to the visible region
// before giving it to the HWC HAL.
const Transform& tr = displayDevice->getTransform();
const auto& viewport = displayDevice->getViewport();
Region visible = tr.transform(visibleRegion.intersect(viewport));
auto hwcId = displayDevice->getHwcDisplayId();
auto& hwcInfo = getBE().mHwcLayers[hwcId];
auto& hwcLayer = hwcInfo.layer;
//设置可见区域
auto error = hwcLayer->setVisibleRegion(visible);
if (error != HWC2::Error::None)
ALOGE("[%s] Failed to set visible region: %s (%d)", mName.string(),
to_string(error).c_str(), static_cast<int32_t>(error));
visible.dump(LOG_TAG);
//设置损坏区域
error = hwcLayer->setSurfaceDamage(surfaceDamageRegion);
if (error != HWC2::Error::None)
ALOGE("[%s] Failed to set surface damage: %s (%d)", mName.string(),
to_string(error).c_str(), static_cast<int32_t>(error));
surfaceDamageRegion.dump(LOG_TAG);
//如果是sideband 图层,直接设置sideband流,然后就返回了
if (getBE().compositionInfo.hwc.sidebandStream.get())
setCompositionType(hwcId, HWC2::Composition::Sideband);
ALOGV("[%s] Requesting Sideband composition", mName.string());
error = hwcLayer->setSidebandStream(getBE().compositionInfo.hwc.sidebandStream->handle());
if (error != HWC2::Error::None)
ALOGE("[%s] Failed to set sideband stream %p: %s (%d)", mName.string(),
getBE().compositionInfo.hwc.sidebandStream->handle(), to_string(error).c_str(),
static_cast<int32_t>(error));
return;
//如果是设备或光标图层,设置相对应的CompositionType
// Device or Cursor layers
if (mPotentialCursor)
ALOGV("[%s] Requesting Cursor composition", mName.string());
setCompositionType(hwcId, HWC2::Composition::Cursor);
else
ALOGV("[%s] Requesting Device composition", mName.string());
setCompositionType(hwcId, HWC2::Composition::Device);
//设置Dataspace
ALOGV("setPerFrameData: dataspace = %d", mCurrentDataSpace);
error = hwcLayer->setDataspace(mCurrentDataSpace);
if (error != HWC2::Error::None)
ALOGE("[%s] Failed to set dataspace %d: %s (%d)", mName.string(), mCurrentDataSpace,
to_string(error).c_str(), static_cast以上是关于Android P 显示流程分析---界面刷新的主要内容,如果未能解决你的问题,请参考以下文章
Android P 显示流程分析---EventThread MessageQueue 交互分析
Android P 显示流程---Display设备初始化过程分析
Android P 显示流程分析--- buffer的生产消费者模式