在介绍HWComposer合成显示流程前,需要先了解下 AndroidO显示体统架构如下图:
- AndroidO显示体统架构如
Linux Android display architecture
其中的SDM架构
- setUpHWComposer介绍
在SurfaceFlinger进行合成显示的时候,首先需要初始化HWC,
代码为setUpHWComposer
void SurfaceFlinger::setUpHWComposer() {
…
for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
…
//判断是否需要重新绘制
bool mustRecompose = dirty && !(empty && wasEmpty);
…
mDisplays[dpy]->beginFrame(mustRecompose);
…
}
…
// build the h/w work list
if (CC_UNLIKELY(mGeometryInvalid)) {
mGeometryInvalid = false;
for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
sp displayDevice(mDisplays[dpy]);
const auto hwcId = displayDevice->getHwcDisplayId();
if (hwcId >= 0) {
const Vector<sp>& currentLayers(
displayDevice->getVisibleLayersSortedByZ());
…
//为每个Layer创建一个与之对应的HwLayer
//并设置Geometry
for (size_t i = 0; i < currentLayers.size(); i++) {
const auto& layer = currentLayers[i];
if (!layer->hasHwcLayer(hwcId)) {
//为layer创建一个与之对应的HwcLayer
if (!layer->createHwcLayer(mHwc.get(), hwcId)) {
//如果创建失败,则强制修改合成方式为Client
layer->forceClientComposition(hwcId);
continue;
}
}
//设置几何尺寸
layer->setGeometry(displayDevice, i);
…
}
}
}
}
// Set the per-frame data
for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) {
auto& displayDevice = mDisplays[displayId];
const auto hwcId = displayDevice->getHwcDisplayId();
...
//为每个Layer设置显示帧数据
for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
layer->setPerFrameData(displayDevice);
}
...
}
...
for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) {
auto& displayDevice = mDisplays[displayId];
if (!displayDevice->isDisplayOn()) {
continue;
}
//尝试直接显示
//如果成功则返回
//如果显示不成功,则会执行刷新validate
status_t result = displayDevice->prepareFrame(*mHwc);
...
}
}
setUpHWComposer有几个重要的过程
判断是否需重新绘制
为每个Layer创建一个与之对应的HwcLayer并设置几何尺寸(Geometry)
为每个Layer及与之对应的HwLayer设置显示帧数据
尝试直接显示
2.1 HwLayer创建
我们首选分析下HwLayer的创建。其简要流程图如下:
在这里插入图片描述
2.2 setGeometry流程
下边分析下setGeometry函数:
//surfaceflinger\Layer.cpp
void Layer::setGeometry(const sp& displayDevice, uint32_t z)
{
const auto hwcId = displayDevice->getHwcDisplayId();
auto& hwcInfo = mHwcLayers[hwcId];
...
hwcInfo.forceClientComposition = false;
...
auto& hwcLayer = hwcInfo.layer;
...
// this gives us only the "orientation" component of the transform
const State& s(getDrawingState());
//设置hwcLayer的blendMode
auto error = hwcLayer->setBlendMode(blendMode);
// apply the layer's transform, followed by the display's global transform
// here we're guaranteed that the layer's transform preserves rects
Region activeTransparentRegion(s.activeTransparentRegion);
Transform t = getTransform();
...
const Transform& tr(displayDevice->getTransform());
Rect transformedFrame = tr.transform(frame);
error = hwcLayer->setDisplayFrame(transformedFrame);
...
FloatRect sourceCrop = computeCrop(displayDevice);
error = hwcLayer->setSourceCrop(sourceCrop);
...
float alpha = getAlpha();
error = hwcLayer->setPlaneAlpha(alpha);
...
error = hwcLayer->setZOrder(z);
...
error = hwcLayer->setInfo(type, appId);
...
/*
* Transformations are applied in this order:
* 1) buffer orientation/flip/mirror
* 2) state transformation (window manager)
* 3) layer orientation (screen orientation)
* (NOTE: the matrices are multiplied in reverse order)
*/
const Transform bufferOrientation(mCurrentTransform);
Transform transform(tr * t * bufferOrientation);
if (getTransformToDisplayInverse()) {
...
transform = Transform(invTransform) * tr * bufferOrientation;
}
// this gives us only the "orientation" component of the transform
const uint32_t orientation = transform.getOrientation();
if (orientation & Transform::ROT_INVALID) {
// we can only handle simple transformation
hwcInfo.forceClientComposition = true;
} else {
auto transform = static_cast<HWC2::Transform>(orientation);
auto error = hwcLayer->setTransform(transform);
...
}
...
}
setGeometry会给HWCLayer设置blendMode、DisplayFrame区域、SourceCrop区域、PlaneAlpha、ZOrder等属性。
基本流程图如下:
在这里插入图片描述
这些区域的含义请参考https://www.jianshu.com/p/824a9ddf68b9这篇大牛博客,我们直接附其一张神图1
在这里插入图片描述
2.3 setPerFrameData流程
下边分析下setPerFrameData
void Layer::setPerFrameData(const sp& 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 = mHwcLayers[hwcId];
auto& hwcLayer = hwcInfo.layer;
auto error = hwcLayer->setVisibleRegion(visible);
…
error = hwcLayer->setSurfaceDamage(surfaceDamageRegion);
…
// Sideband layers
if (mSidebandStream.get()) {
setCompositionType(hwcId, HWC2::Composition::Sideband);
error = hwcLayer->setSidebandStream(mSidebandStream->handle());
...
return;
}
// Client layers
if (hwcInfo.forceClientComposition ||
(mActiveBuffer != nullptr && mActiveBuffer->handle == nullptr)) {
setCompositionType(hwcId, HWC2::Composition::Client);
return;
}
// SolidColor layers
if (mActiveBuffer == nullptr) {
setCompositionType(hwcId, HWC2::Composition::SolidColor);
// For now, we only support black for DimLayer
error = hwcLayer->setColor({0, 0, 0, 255});
...
// Clear out the transform, because it doesn't make sense absent a
// source buffer
error = hwcLayer->setTransform(HWC2::Transform::None);
...
return;
}
// Device or Cursor layers
if (mPotentialCursor) {
// 如果mPotentialCursor为true,设置合成方式为Cursor
setCompositionType(hwcId, HWC2::Composition::Cursor);
} else {
//设置合成方式为Device,Layer的默认值合成方式
setCompositionType(hwcId, HWC2::Composition::Device);
}
...
//设置dataspace
error = hwcLayer->setDataspace(mCurrentState.dataSpace);
...
uint32_t hwcSlot = 0;
sp<GraphicBuffer> hwcBuffer;
hwcInfo.bufferCache.getHwcBuffer(mActiveBufferSlot, mActiveBuffer,
&hwcSlot, &hwcBuffer);
auto acquireFence = mSurfaceFlingerConsumer->getCurrentFence();
//设置hwcLayer的hwcBuffer和acquireFence
error = hwcLayer->setBuffer(hwcSlot, hwcBuffer, acquireFence);
}
setPerFrameData流程图如下:
在这里插入图片描述
至此,所有hwcLayer都设置完成合成方式和合成显示帧数据后,便可以调用displayDevice->prepareFrame(*mHwc)尝试直接显示,下边分析下该函数
2.3 prepareFrame分析
status_t DisplayDevice::prepareFrame(HWComposer& hwc) {
//调用hwc.prepare尝试显示
status_t error = hwc.prepare(*this);
…
//mDisplaySurface 为FramebufferSurface.cpp
//空实现
return mDisplaySurface->prepareFrame(compositionType);
}
下边我们分析下HWComposer::prepare
status_t HWComposer::prepare(DisplayDevice& displayDevice) {
…
auto displayId = displayDevice.getHwcDisplayId();
…
auto& displayData = mDisplayData[displayId];
auto& hwcDisplay = displayData.hwcDisplay;
if (!hwcDisplay->isConnected()) {
return NO_ERROR;
}
uint32_t numTypes = 0;
uint32_t numRequests = 0;
HWC2::Error error = HWC2::Error::None;
// First try to skip validate altogether if the HWC supports it.
displayData.validateWasSkipped = false;
//如果HWC支持SkipValidate且没有合成方式为Client,即hasClientComposition为false
//尝试直接显示,如果不能直接显示则执行Validate
if (hasCapability(HWC2::Capability::SkipValidate) &&
!displayData.hasClientComposition) {
sp<android::Fence> outPresentFence;
uint32_t state = UINT32_MAX;
//首先会尝试直接显示,如果state == 1,表示显示成功
//如果不能直接显示则尝试Validate,如果如果state == 0,表示validate成功
error = hwcDisplay->presentOrValidate(&numTypes, &numRequests, &outPresentFence , &state);
...
//如果显示成功了,则直接返回了,不必执行其他操作
if (state == 1) { //Present Succeeded.
std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences;
error = hwcDisplay->getReleaseFences(&releaseFences);
displayData.releaseFences = std::move(releaseFences);
displayData.lastPresentFence = outPresentFence;
displayData.validateWasSkipped = true;
displayData.presentError = error;
return NO_ERROR;
}
// Present failed but Validate ran.
} else {
//尝试更新validate
error = hwcDisplay->validate(&numTypes, &numRequests);
}
...
std::unordered_map<HWC2::Layer*, HWC2::Composition> changedTypes;
changedTypes.reserve(numTypes);
//执行完validate后,hwc会检查之前设置的合成方式是否支持
//如果不支持,则会尝试修改,通过getChangedCompositionTypes
//可以获取需要修改合成方式的HWcLayer和修改的合成方式
error = hwcDisplay->getChangedCompositionTypes(&changedTypes);
...
displayData.displayRequests = static_cast<HWC2::DisplayRequest>(0);
std::unordered_map<HWC2::Layer*, HWC2::LayerRequest> layerRequests;
layerRequests.reserve(numRequests);
error = hwcDisplay->getRequests(&displayData.displayRequests,
&layerRequests);
...
displayData.hasClientComposition = false;
displayData.hasDeviceComposition = false;
for (auto& layer : displayDevice.getVisibleLayersSortedByZ()) {
auto hwcLayer = layer->getHwcLayer(displayId);
//检查hwcLayer是否在changedTypes中,
//如果在,则会修改其合成方式为changedTypes[hwcLayer]
if (changedTypes.count(hwcLayer) != 0) {
// We pass false so we only update our state and don't call back
// into the HWC device
//首先检查先新的合成方式changedTypes[hwcLayer]
validateChange(layer->getCompositionType(displayId),
changedTypes[hwcLayer]);
//修改合成方式为 changedTypes[hwcLayer]
layer->setCompositionType(displayId, changedTypes[hwcLayer], false);
}
//如果存在Client合成,则将hasClientComposition置为true
//如果存在Device合成,则将hasDeviceComposition置为true
switch (layer->getCompositionType(displayId)) {
case HWC2::Composition::Client:
displayData.hasClientComposition = true;
break;
case HWC2::Composition::Device:
case HWC2::Composition::SolidColor:
case HWC2::Composition::Cursor:
case HWC2::Composition::Sideband:
displayData.hasDeviceComposition = true;
break;
default:
break;
}
//如果hwcLayer在layerRequests且值为ClearClientTarget
//则设置layer的ClearClientTarget标志位,
//表示是否需要清理Client合成结果
//否则置为false
if (layerRequests.count(hwcLayer) != 0 &&
layerRequests[hwcLayer] ==
HWC2::LayerRequest::ClearClientTarget) {
layer->setClearClientTarget(displayId, true);
} else {
...
layer->setClearClientTarget(displayId, false);
}
}
//通知Hwc做相应修改
error = hwcDisplay->acceptChanges();
...
return NO_ERROR;
}
我们分析下presentOrValidate流程,Validate流程在presentOrValidate失败时会执行,所以在分析presentOrValidate,其实也会分析Validate流程。
//ComposerHal.cpp
Error Composer::presentOrValidateDisplay(Display display, uint32_t* outNumTypes,
uint32_t* outNumRequests, int* outPresentFence, uint32_t* state) {
mWriter.selectDisplay(display);
mWriter.presentOrvalidateDisplay();
//提交合成显示命令给IComposer服务
Error error = execute();
//读取结果
mReader.takePresentOrValidateStage(display, state);
//如果state == 1表示 Present succeeded
if (*state == 1) { // Present succeeded
mReader.takePresentFence(display, outPresentFence);
}
//如果state == 0表示 Validate succeeded
if (*state == 0) { // Validate succeeded.
mReader.hasChanges(display, outNumTypes, outNumRequests);
}
return Error::NONE;
}
我们来分析下Composer::execute是如何提交合成显示命令的
//ComposerHal.cpp
Error Composer::execute()
{
// prepare input command queue
bool queueChanged = false;
uint32_t commandLength = 0;
hidl_vec<hidl_handle> commandHandles;
//将mWriter的合成显示命令提交给commandHandles
if (!mWriter.writeQueue(&queueChanged, &commandLength, &commandHandles)) {
mWriter.reset();
return Error::NO_RESOURCES;
}
// set up new input command queue if necessary
if (queueChanged) {
auto ret = mClient->setInputCommandQueue(*mWriter.getMQDescriptor());
auto error = unwrapRet(ret);
...
}
//mClient 为IComposerClient代理对象
//通过该代理对象提交合成显示命令
Error error = kDefaultError;
auto ret = mClient->executeCommands(commandLength, commandHandles,
[&](const auto& tmpError, const auto& tmpOutChanged,
const auto& tmpOutLength, const auto& tmpOutHandles)
{
error = tmpError;
// set up new output command queue if necessary
...
});
...
return error;
}
通过上边的分析发现,只有执行Composer::execute才会将合成显示命令提交给IComposer服务做进一步的合成显示。
- Client合成Layer渲染至FBTarget
至此每个Layer的合成显示数据及合成方式都确定了,接着调用doComposition来实现最后的合成显示
如果在prepareFrame时,已经成功显示了,则doComposition只会清理下commandbuffer
如果prepareFrame时,显示不成功,则由doComposition来完成剩余的工作,如存在client合成则调用OpenGL进行合成。
void SurfaceFlinger::doComposition() {
…
for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
const sp& hw(mDisplays[dpy]);
if (hw->isDisplayOn()) {
// transform the dirty region into this screen’s coordinate space
const Region dirtyRegion(hw->getDirtyRegion(repaintEverything));
// repaint the framebuffer (if needed)
//主要处理client合成
doDisplayComposition(hw, dirtyRegion);
...
}
}
//提交合成显示命令给HWC
postFramebuffer();
}
1
3.1 doDisplayComposition介绍
void SurfaceFlinger::doDisplayComposition(
const sp& displayDevice,
const Region& inDirtyRegion)
{
// 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)
…
//主要是执行client合成
//将需要Client合成的Layer全部绘制到FBTarget上
if (!doComposeSurfaces(displayDevice, dirtyRegion)) return;
…
{
// update the swap region and clear the dirty region
displayDevice->swapRegion.orSelf(dirtyRegion);
// swap buffers (presentation)
//调用eglswapbuffer,交换前后buffer
displayDevice->swapBuffers(getHwComposer());
}
}
bool SurfaceFlinger::doComposeSurfaces(
const sp& displayDevice, const Region& dirty)
{
…
//检查是否存在client合成的Layer
bool hasClientComposition = mHwc->hasClientComposition(hwcId);
if (hasClientComposition) {
…
//eglMakeCurrent
//glViewport(0, 0, vpw, vph);
//获取透视矩阵mProjectionMatrix
if (!displayDevice->makeCurrent(mEGLDisplay, mEGLContext)) {
…
return false;
}
…
//检查是否存在Device合成的Layer
const bool hasDeviceComposition = mHwc->hasDeviceComposition(hwcId);
if (hasDeviceComposition) {
//清理FBTarget为(0, 0, 0, 0)透明
mRenderEngine->clearWithColor(0, 0, 0, 0);
} else {
//如果Layer全部是Client合成
//计算dirty region
…
// screen is already cleared here
if (!region.isEmpty()) {
// can happen with SurfaceView
//清理FBTarget的region对应的区域
drawWormhole(displayDevice, region);
}
}
…
}
/*
* and then, render the layers targeted at the framebuffer
*/
//绘制需Client合成的Layer
if (hwcId >= 0) {
// we’re using h/w composer
bool firstLayer = true;
for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
const Region clip(dirty.intersect(
displayTransform.transform(layer->visibleRegion)));
…
if (!clip.isEmpty()) {
switch (layer->getCompositionType(hwcId)) {
case HWC2::Composition::Cursor:
case HWC2::Composition::Device:
case HWC2::Composition::Sideband:
case HWC2::Composition::SolidColor: {
const Layer::State& state(layer->getDrawingState());
//如果ClearClientTarget为true,且不是第一个Layer
//说明存在其他Layer为Client合成
if (layer->getClearClientTarget(hwcId) && !firstLayer &&
layer->isOpaque(state) && (layer->getAlpha() == 1.0f)
&& hasClientComposition) {
// never clear the very first layer since we’re
// guaranteed the FB is already cleared
//如果Layer是Device合成,则通过OpenGL清理layer在FBTarget上的对应区域
layer->clearWithOpenGL(displayDevice);
}
break;
}
case HWC2::Composition::Client: {
//如果是Client合成,则直接调用OpenGl绘制到FBTarget,区域为clip
//具体opengl实现,我们就不介绍了,这一部分需要有一些opengl的知识
layer->draw(displayDevice, clip);
break;
}
default:
break;
}
}
firstLayer = false;
}
}
…
return true;
}
至此FBTarget绘制完成,简单总结下:
首先如果display中的Layer存在client合成,则需要绑定glcontext,设置viewport
调用opengl做一些清理工作
对client合成Layer使用OpenGL渲染合成至FBTarget上
3.2 swapBuffers介绍
至此,需client合成的Layer已经使用OpenGL渲染合成至FBTarget上了,接着需要执行swapBuffers交换前后buffer,并将渲染结果提交给Hwccomposer
void DisplayDevice::swapBuffers(HWComposer& hwc) const {
…
//如果存在Client合成
if (hwc.hasClientComposition(mHwcDisplayId)
|| hwc.hasFlipFBTRequest(mHwcDisplayId)) {
…
//交换前后buffer
EGLBoolean success = eglSwapBuffers(mDisplay, mSurface);
…
}
…
//获取渲染结果并提交给hwc
status_t result = mDisplaySurface->advanceFrame();
…
}
获取FBTarget渲染结果并提交给hwc
status_t FramebufferSurface::advanceFrame() {
…
uint32_t slot = 0;
sp buf;
sp acquireFence(Fence::NO_FENCE);
android_dataspace_t dataspace = HAL_DATASPACE_UNKNOWN;
//通过acquireBuffer获取bufferqueue中一个queue状态的buffer
//后边肯定会有一个releaBuffer
status_t result = nextBuffer(slot, buf, acquireFence, dataspace);
…
return result;
}
status_t FramebufferSurface::nextBuffer(uint32_t& outSlot,
sp& outBuffer, sp& outFence,
android_dataspace_t& outDataspace) {
…
BufferItem item;
//通过acquireBuffer获取bufferqueue中一个queue状态的buffer
//后边肯定会有一个releaBuffer
status_t err = acquireBufferLocked(&item, 0);
…
//通过获取的item更新mCurrentBuffer
mCurrentBufferSlot = item.mSlot;
mCurrentBuffer = mSlots[mCurrentBufferSlot].mGraphicBuffer;
mCurrentFence = item.mFence;
outFence = item.mFence;
//在mHwcBufferCache中查找mCurrentBuffer并返回查找结果outBuffer、outSlot
mHwcBufferCache.getHwcBuffer(mCurrentBufferSlot, mCurrentBuffer,
&outSlot, &outBuffer);
outDataspace = item.mDataSpace;
//设置渲染结果提交给mHwc
status_t result =
mHwc.setClientTarget(mDisplayType, outSlot, outFence, outBuffer, outDataspace);
…
return NO_ERROR;
}
Error Composer::setClientTarget(Display display, uint32_t slot,
const sp& target,
int acquireFence, Dataspace dataspace,
const std::vectorIComposerClient::Rect& damage)
{
mWriter.selectDisplay(display);
…
const native_handle_t* handle = nullptr;
if (target.get()) {
handle = target->getNativeBuffer()->handle;
}
//将渲染结果写入mWriter
mWriter.setClientTarget(slot, handle, acquireFence, dataspace, damage);
return Error::NONE;
}
3.3 postFramebuffer()分析
至此,将渲染结果写入了mWriter,需要执行postFramebuffer将FBtarget提交给IComposer服务进行渲染
void SurfaceFlinger::postFramebuffer()
{
…
const nsecs_t now = systemTime();
mDebugInSwapBuffers = now;
for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) {
auto& displayDevice = mDisplays[displayId];
if (!displayDevice->isDisplayOn()) {
continue;
}
const auto hwcId = displayDevice->getHwcDisplayId();
if (hwcId >= 0) {
//提交合成显示命令给IComposer
mHwc->presentAndGetReleaseFences(hwcId);
}
//执行releaseBufferLocked,将buffer归还给bufferqueue中
displayDevice->onSwapBuffersCompleted();
displayDevice->makeCurrent(mEGLDisplay, mEGLContext);
//更新layer的release
for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
...
sp<Fence> releaseFence = Fence::NO_FENCE;
if (hwcId >= 0) {
auto hwcLayer = layer->getHwcLayer(hwcId);
releaseFence = mHwc->getLayerReleaseFence(hwcId, hwcLayer);
}
if (layer->getCompositionType(hwcId) == HWC2::Composition::Client) {
releaseFence = Fence::merge("LayerRelease", releaseFence,
displayDevice->getClientTargetAcquireFence());
}
layer->onLayerDisplayed(releaseFence);
}
...
}
}
下边分析下presentAndGetReleaseFences
status_t HWComposer::presentAndGetReleaseFences(int32_t displayId) {
…
auto& displayData = mDisplayData[displayId];
auto& hwcDisplay = displayData.hwcDisplay;
//在DisplayDevice::prepareFrame尝试直接显示的时候
//如果直接显示成功会将displayData.validateWasSkipped置为true
if (displayData.validateWasSkipped) {
bool discardCommands = true;
…
if (discardCommands) {
//清理调commandbuffer,并直接返回
hwcDisplay->discardCommands();
}
auto error = displayData.presentError;
…
return NO_ERROR;
}
//至此所有Layer及FBTarget都有合成显示buffer及其他相关信息了
//调用hwcDisplay->present执行显示
auto error = hwcDisplay->present(&displayData.lastPresentFence);
…
std::unordered_map<HWC2::Layer*, sp> releaseFences;
//获取hwc返回的releasefence
error = hwcDisplay->getReleaseFences(&releaseFences);
…
//保存到displayData.releaseFences
displayData.releaseFences = std::move(releaseFences);
return NO_ERROR;
}
3.4 releaseBuffer流程分析
下边分析onSwapBuffersCompleted
void DisplayDevice::onSwapBuffersCompleted() const {
mDisplaySurface->onFrameCommitted();
}
void FramebufferSurface::onFrameCommitted() {
if (mHasPendingRelease) {
sp fence = mHwc.getPresentFence(mDisplayType);
if (fence->isValid()) {
//更新releasefence
status_t result = addReleaseFence(mPreviousBufferSlot,
mPreviousBuffer, fence);
}
//归还buffer给bufferqueue
status_t result = releaseBufferLocked(mPreviousBufferSlot,
mPreviousBuffer, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR);
…
mPreviousBuffer.clear();
mHasPendingRelease = false;
}
}
5 IComposer服务响应presentOrValidateDisplay流程
前边分析了SurfaceFlinger中的合成显示流程,SurfaceFlinger会将合成显示命令提交给IComposer在继续完成合成显示。下边我们分析下
IComposer服务响应presentOrValidateDisplay的流程:
//ap\hardware\interfaces\graphics\composer\2.1\default\ComposerClient.cpp
bool ComposerClient::CommandReader::parsePresentOrValidateDisplay(uint16_t length)
{
…
// First try to Present as is.
int presentFence = -1;
std::vector layers;
std::vector fences;
//mHal为HwcHal对象
//最终会调用HWCSession::PresentDisplay
//HWCSession是一个hwc2_device_t设备对象
auto err = mHal.presentDisplay(mDisplay, &presentFence, &layers, &fences);
//显示成功
if (err == Error::NONE) {
//设置parsePresentOrValidateDisplay结果为1
mWriter.setPresentOrValidateResult(1);
mWriter.setPresentFence(presentFence);
//设置ReleaseFence
mWriter.setReleaseFences(layers, fences);
return true;
}
// Present has failed. We need to fallback to validate
//如果显示失败,则会执行validate
std::vector changedLayers;
std::vectorIComposerClient::Composition compositionTypes;
uint32_t displayRequestMask = 0x0;
std::vector requestedLayers;
std::vector<uint32_t> requestMasks;
//mHal为HWCSession对象
err = mHal.validateDisplay(mDisplay, &changedLayers,
&compositionTypes, &displayRequestMask,
&requestedLayers, &requestMasks);
if (err == Error::NONE) {
//设置parsePresentOrValidateDisplay结果为0
mWriter.setPresentOrValidateResult(0);
//修改合成方式
mWriter.setChangedCompositionTypes(changedLayers,
compositionTypes);
//设置DisplayRequests
mWriter.setDisplayRequests(displayRequestMask,
requestedLayers, requestMasks);
} else {
mWriter.setError(getCommandLoc(), err);
}
return true;
}
接着分析下HWCSession::PresentDisplay
int32_t HWCSession::PresentDisplay(hwc2_device_t *device, hwc2_display_t display,
int32_t *out_retire_fence) {
HWCSession *hwc_session = static_cast<HWCSession *>(device);
…
if (hwc_session->hwc_display_[display]) {
//hwc_display_类型有几种,我们只介绍下HWCDisplayPrimary
status = hwc_session->hwc_display_[display]->Present(out_retire_fence);
…
}
…
return INT32(status);
}
接着分析下present
//ap\hardware\qcom\display\sdm\libs\hwc2\hwc_display_builtin.cpp
HWC2::Error HWCDisplayPrimary::Present(int32_t *out_retire_fence) {
auto status = HWC2::Error::None;
if (display_paused_) {
…
} else {
status = HWCDisplay::CommitLayerStack();
if (status == HWC2::Error::None) {
HandleFrameOutput();
SolidFillCommit();
status = HWCDisplay::PostCommitLayerStack(out_retire_fence);
}
}
pending_commit_ = false;
return status;
}
接着分下下CommitLayerStack
//hwc_display.cpp
HWC2::Error HWCDisplay::CommitLayerStack(void) {
…
DumpInputBuffers();
…
//display_intf_有三种类型
//DisplayPrimary、DisplayHDMI、DisplayVirtual
//我们只分析下DisplayPrimary
error = display_intf_->Commit(&layer_stack_);
…
skip_validate_ = true;
return HWC2::Error::None;
}
//display_primary.cpp
DisplayError DisplayPrimary::Commit(LayerStack *layer_stack) {
…
error = DisplayBase::Commit(layer_stack);
…
return error;
}
DisplayError DisplayBase::Commit(LayerStack *layer_stack) {
…
DisplayError error = kErrorNone;
…
DLOGI_IF(kTagDisplay, “Entering commit for display type : %d”, display_type_);
CommitLayerParams(layer_stack);
…
error = comp_manager_->Commit(display_comp_ctx_, &hw_layers_);
…
//hw_intf_有几种类型
//kPrimary:HWPeripheralDRM
//kHDMI:HWTVDRM
//kVirtual:HWVirtualDRM
error = hw_intf_->Commit(&hw_layers_);
…
PostCommitLayerParams(layer_stack);
…
error = comp_manager_->PostCommit(display_comp_ctx_, &hw_layers_);
DLOGI_IF(kTagDisplay, “Exiting commit for display type : %d”, display_type_);
return kErrorNone;
}
DisplayError HWPeripheralDRM::Commit(HWLayers *hw_layers) {
HWLayersInfo &hw_layer_info = hw_layers->info;
SetDestScalarData(hw_layer_info);
return HWDeviceDRM::Commit(hw_layers);
}
最终的提交在:
//hardware\qcom\display\sdm\libs\core\drm\hw_device_drm.cpp
DisplayError HWDeviceDRM::Commit(HWLayers *hw_layers) {
…
DisplayError err = kErrorNone;
registry_.RegisterCurrent(hw_layers);
//目前default_mode_为false
if (default_mode_) {
err = DefaultCommit(hw_layers);
} else {
err = AtomicCommit(hw_layers);
}
registry_.UnregisterNext();
return err;
}
DisplayError HWDeviceDRM::AtomicCommit(HWLayers hw_layers) {
…
SetupAtomic(hw_layers, false / validate /);
…
//drm_atomic_intf_是在ap\hardware\qcom\display\libdrmutils\drm_lib_loader.cpp中
//通过dlopen(libsdedrm.so)获取的方法
//libsdedrm.so源码高通并未开源
int ret = drm_atomic_intf_->Commit(false / synchronous /, false / retain_planes*/);
int release_fence = -1;
int retire_fence = -1;
drm_atomic_intf_->Perform(DRMOps::CRTC_GET_RELEASE_FENCE, token_.crtc_id, &release_fence);
drm_atomic_intf_->Perform(DRMOps::CONNECTOR_GET_RETIRE_FENCE, token_.conn_id, &retire_fence);
…
return kErrorNone;
}
在继续分析前需要先了解几个结构体
/*! @brief This structure defines a layer stack that contains layers which need to be composed and
rendered onto the target.
*/
struct LayerStack {
std::vector<Layer > layers = {}; //!< Vector of layer pointers.
…
}
/! @brief This structure defines display layer object which contains layer properties and a drawing
buffer.
@sa LayerArray
*/
struct Layer {
LayerBuffer input_buffer = {}; //!< Buffer to be composed.
//!< If this remains unchanged between two
//!< consecutive Prepare() calls and
//!< geometry_changed flag is not set for the
//!< second call, then the display device will
//!< assume that buffer content has not
//!< changed.
LayerComposition composition = kCompositionGPU; //!< Composition type which can be set by either
//!< the client or the display device. This value
//!< should be preserved between Prepare() and
//!< Commit() calls.
LayerRect src_rect = {}; //!< Rectangular area of the layer buffer to
//!< consider for composition.
LayerRect dst_rect = {}; //!< The target position where the frame will be
//!< displayed. Cropping rectangle is scaled to
//!< fit into this rectangle. The origin is the
//!< top-left corner of the screen.
std::vector visible_regions = {}; //!< Visible rectangular areas in screen space.
//!< The visible region includes areas overlapped
//!< by a translucent layer.
std::vector dirty_regions = {}; //!< Rectangular areas in the current frames
//!< that have changed in comparison to
//!< previous frame.
std::vector blit_regions = {}; //!< Rectangular areas of this layer which need
//!< to be composed to blit target. Display
//!< device will update blit rectangles if a
//!< layer composition is set as hybrid. Nth blit
//!< rectangle shall be composed onto Nth blit
//!< target.
LayerBlending blending = kBlendingPremultiplied; //!< Blending operation which need to be
//!< applied on the layer buffer during
//!< composition.
LayerTransform transform = {}; //!< Rotation/Flip operations which need to be
//!< applied to the layer buffer during
//!< composition.
uint8_t plane_alpha = 0xff; //!< Alpha value applied to the whole layer.
//!< Value of each pixel is computed as:
//!< if(kBlendingPremultiplied) {
//!< pixel.RGB = pixel.RGB * planeAlpha/255
//!< }
//!< pixel.a = pixel.a * planeAlpha
uint32_t frame_rate = 0; //!< Rate at which frames are being updated for
//!< this layer.
uint32_t solid_fill_color = 0; //!< TODO: Remove this field when fb support
//! is deprecated.
//!< Solid color used to fill the layer when
//!< no content is associated with the layer.
LayerFlags flags; //!< Flags associated with this layer.
LayerRequest request = {}; //!< o/p - request on this Layer by SDM.
Lut3d lut_3d = {}; //!< o/p - Populated by SDM when tone mapping is
//!< needed on this layer.
LayerSolidFill solid_fill_info = {}; //!< solid fill info along with depth.
}
图片来源于https://www.jianshu.com/p/824a9ddf68b9,如有侵权,请告知删除,谢谢。 ↩︎