电子商务网站建设与管理课程论文,建筑公司网站源码下载,wordpress自定义右侧不显示页面,怎么打开到wordpressOpenHarmony送显流程分析
引言 本文档主要记录OpenHarmony在渲染完成之后如何进行合成和送显流程的。这个过程牵涉的代码很多#xff0c;而且流程也是比较繁琐的。所以我一定要坚持下来。千万不能半途而废#xff0c;也不要想着一口气吃出一个胖子#xff0c;路漫漫其修远兮… OpenHarmony送显流程分析
引言 本文档主要记录OpenHarmony在渲染完成之后如何进行合成和送显流程的。这个过程牵涉的代码很多而且流程也是比较繁琐的。所以我一定要坚持下来。千万不能半途而废也不要想着一口气吃出一个胖子路漫漫其修远兮吾将上下而求索 一. 应用端发送NextVSnc请求服务端响应 还记得那年大明湖畔的夏雨荷吗错了还记得前面我们在分析OH的buffer管理的时候当bootamition渲染完成之后会调用flush将buffer的使用权还给render_server吗不记得也没有关系我们重新来看下
RSRenderServiceListener::OnBufferAvailable(...)RSMainThread::Instance()-RequestNextVSync(...)//触发下次vsyncvoid RSMainThread::RequestNextVSync()
{RS_TRACE_FUNC();VSyncReceiver::FrameCallback fcb {.userData_ this,.callback_ [this](uint64_t timestamp, void* data) { OnVsync(timestamp, data); },//回调函数};if (receiver_ ! nullptr) {requestNextVsyncNum_;if (requestNextVsyncNum_ RUQUEST_VSYNC_NUMBER_LIMIT) {RS_LOGW(RSMainThread::RequestNextVSync too many times:%d, requestNextVsyncNum_);}receiver_-RequestNextVSync(fcb);//这里我们重点分析下receiver_详见章节1.1}
}void RSMainThread::OnVsync(uint64_t timestamp, void* data)
{ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, RSMainThread::OnVsync);timestamp_ timestamp;requestNextVsyncNum_ 0;if (isUniRender_) {MergeToEffectiveTransactionDataMap(cachedTransactionDataMap_);RSUnmarshalThread::Instance().PostTask(unmarshalBarrierTask_);}mainLoop_();if (handler_) {auto screenManager_ CreateOrGetScreenManager();if (screenManager_ ! nullptr) {PostTask([]() { screenManager_-ProcessScreenHotPlugEvents(); });}}ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);
}
1.1 VSyncReceiver初始化
代码分析无需多言。直接干就完了上代码直接开撸
//rs_main_thread.cpp
void RSMainThread::Init()
{...//这套就是模仿Android做的通过LocalSocketPairhandler_ std::make_sharedAppExecFwk::EventHandler(runner_);sptrVSyncConnection conn new VSyncConnection(rsVSyncDistributor_, rs);rsVSyncDistributor_-AddConnection(conn);receiver_ std::make_sharedVSyncReceiver(conn, handler_);receiver_-Init();...}1.2 RequestNextVSync
//vsync_receiver.cpp
VsyncError VSyncReceiver::RequestNextVSync(FrameCallback callback)
{std::lock_guardstd::mutex locker(initMutex_);if (!init_) {return VSYNC_ERROR_API_FAILED;}listener_-SetCallback(callback);ScopedBytrace func(VSyncReceiver::RequestNextVSync_pid: std::to_string(GetRealPid()) _name: name_);return connection_-RequestNextVSync();
}1.3 VSyncConnection::RequestNextVSync
VsyncError VSyncConnection::RequestNextVSync()
{...return distributor-RequestNextVSync(this);
}VsyncError VSyncDistributor::RequestNextVSync(const sptrVSyncConnection connection)
{...if (connection-rate_ 0) {...//此时会唤醒VSyncDistributor线程con_.notify_all();//notify all tasks...}...
}void VSyncDistributor::ThreadMain()
{...while (vsyncThreadRunning_ true) {for (uint32_t i 0; i conns.size(); i) {int32_t ret conns[i]-PostEvent(timestamp);}...}}int32_t VSyncConnection::PostEvent(int64_t now)
{//这个地方发给谁接收了得找找找int32_t ret socketPair_-SendData(now, sizeof(int64_t));}//上面分析感觉没有和底层的vsync对接上吗1.4 遗留问题
这里有一个遗留问题就是vsync间隔时间是怎么计算出来的这里我没有找到是怎么和底层的vblack关联起来的还有它走的是soft vsync还是硬的。它的计算规则是怎样的 二. 应用端响应VSync事件
这里还是以bootamition举例其它的应用流程也基本相似(主要是我对其它的应用也不是很熟悉所以只能重复的以bootamition举例来说明了.)
std::shared_ptrOHOS::Rosen::VSyncReceiver receiver_ nullptr;
void BootAnimation::Init(int32_t width, int32_t height)
{...auto rsClient OHOS::Rosen::RSInterfaces::GetInstance();/**RSInterfaces RSInterfaces::GetInstance(){static RSInterfaces instance;return instance;}RSInterfaces::RSInterfaces() : renderServiceClient_(std::make_uniqueRSRenderServiceClient()){}**/while (receiver_ nullptr) {receiver_ rsClient.CreateVSyncReceiver(BootAnimation, mainHandler_);//这里获取的是代理端/*** std::shared_ptrVSyncReceiver RSInterfaces::CreateVSyncReceiver(const std::string name,const std::shared_ptrOHOS::AppExecFwk::EventHandler looper){return renderServiceClient_-CreateVSyncReceiver(name, looper);}std::shared_ptrVSyncReceiver RSRenderServiceClient::CreateVSyncReceiver(const std::string name,const std::shared_ptrOHOS::AppExecFwk::EventHandler looper){auto renderService RSRenderServiceConnectHub::GetRenderService();if (renderService nullptr) {return nullptr;}sptrIVSyncConnection conn renderService-CreateVSyncConnection(name);return std::make_sharedVSyncReceiver(conn, looper, name);}***/}VsyncError ret receiver_-Init();OHOS::Rosen::VSyncReceiver::FrameCallback fcb {.userData_ this,.callback_ std::bind(BootAnimation::OnVsync, this),};int32_t changefreq static_castint32_t((1000.0 / freq_) / 16);ret receiver_-SetVSyncRate(fcb, changefreq);...
}
应用端接收和响应vsync事件主要用于自身的绘制和渲染工作。当然也可以不干任何事情仅仅接收。这个取决于业务逻辑这块不是我们重点讨论的内容 三. render_service响应VSync事件
这里注意是render_service响应VSync事件不是NextVsync。理解清楚了上述点下面我们来接着分析
//rs_main_thread.cpp
void RSMainThread::OnVsync(uint64_t timestamp, void* data)
{...mainLoop_();//详见章节3.1if (handler_) {auto screenManager_ CreateOrGetScreenManager();if (screenManager_ ! nullptr) {PostTask([]() { screenManager_-ProcessScreenHotPlugEvents(); });//这个地方后续详细分析}}...
}3.1 mainLoop_流程分析
C的语法经常会有一些牛鬼蛇神的用法所以我们要报着见怪不怪的心态开搞就好
//rs_main_thread.cpp mainLoop_ []() {RS_LOGD(RsDebug mainLoop start);PerfMultiWindow();RenderFrameTrace::GetInstance().RenderStartFrameTrace(RS_INTERVAL_NAME);SetRSEventDetectorLoopStartTag();ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, RSMainThread::DoComposition);ConsumeAndUpdateAllNodes();//详见章节3.2WaitUntilUnmarshallingTaskFinished();ProcessCommand();Animate(timestamp_);CheckColdStartMap();CheckDelayedSwitchTask();Render();//详见章节3.3ReleaseAllNodesBuffer();SendCommands();ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);SetRSEventDetectorLoopFinishTag();rsEventManager_.UpdateParam();RS_LOGD(RsDebug mainLoop end);};//在最最开始会创建DisplayRenderNode然后添加到RootNode里面去注意只会添加一次
01-01 08:00:14.535 670 1395 E C01400/OHOS::ROSEN: RSDisplayNode::Create, id:2877628088321
01-01 08:00:14.662 670 1395 E C01400/OHOS::ROSEN: RSDisplayNode::Create Tid:1395 comm:EventRunner#1
01-01 08:00:14.662 670 1395 E C01400/OHOS::ROSEN: #00 pc 0000000000018ff4 /system/lib64/lib_dfx_dump_catcher.z.so(OHOS::HiviewDFX::DfxDumpCatcher::DumpCatch(int, int, std::__h::basic_stringchar, std::__h::char_traitschar, std::__h::allocatorchar )152)
01-01 08:00:14.662 670 1395 E C01400/OHOS::ROSEN: #01 pc 00000000000887f0 /system/lib64/librender_service_client.z.so(OHOS::Rosen::RSDisplayNode::Create(OHOS::Rosen::RSDisplayNodeConfig const)600)
01-01 08:00:14.662 670 1395 E C01400/OHOS::ROSEN: #02 pc 000000000003bae4 /system/lib64/libdms.z.so(OHOS::Rosen::AbstractScreen::InitRSDisplayNode(OHOS::Rosen::RSDisplayNodeConfig, OHOS::Rosen::Point)88)
01-01 08:00:14.662 670 1395 E C01400/OHOS::ROSEN: #03 pc 000000000003d3dc /system/lib64/libdms.z.so(OHOS::Rosen::AbstractScreenGroup::AddChild(OHOS::sptrOHOS::Rosen::AbstractScreen, OHOS::Rosen::Point)172)
01-01 08:00:14.662 670 1395 E C01400/OHOS::ROSEN: #04 pc 0000000000044ea4 /system/lib64/libdms.z.so(OHOS::Rosen::AbstractScreenController::AddAsFirstScreenLocked(OHOS::sptrOHOS::Rosen::AbstractScreen)832)
01-01 08:00:14.662 670 1395 E C01400/OHOS::ROSEN: #05 pc 0000000000043088 /system/lib64/libdms.z.so(OHOS::Rosen::AbstractScreenController::AddToGroupLocked(OHOS::sptrOHOS::Rosen::Abstract01-01 08:00:14.554 690 690 E C01400/OHOS::RS: RSDisplayRenderNode create Tid:690 comm:render_service
01-01 08:00:14.554 690 690 E C01400/OHOS::RS: #00 pc 0000000000018ff4 /system/lib64/lib_dfx_dump_catcher.z.so(OHOS::HiviewDFX::DfxDumpCatcher::DumpCatch(int, int, std::__h::basic_stringchar, std::__h::char_traitschar, std::__h::allocatorchar )152)
01-01 08:00:14.554 690 690 E C01400/OHOS::RS: #01 pc 00000000000d5b84 /system/lib64/librender_service_base.z.so(OHOS::Rosen::RSDisplayRenderNode::RSDisplayRenderNode(unsigned long, OHOS::Rosen::RSDisplayNodeConfig const, std::__h::weak_ptrOHOS::Rosen::RSContext)384)
01-01 08:00:14.554 690 690 E C01400/OHOS::RS: #02 pc 00000000000bd7c4 /system/lib64/librender_service_base.z.so
01-01 08:00:14.554 690 690 E C01400/OHOS::RS: #03 pc 00000000000bcf24 /system/lib64/librender_service_base.z.so(OHOS::Rosen::DisplayNodeCommandHelper::Create(OHOS::Rosen::RSContext, unsigned long, OHOS::Rosen::RSDisplayNodeConfig const)108)
01-01 08:00:14.554 690 690 E C01400/OHOS::RS: #04 pc 000000000006dcd8 /system/lib64/librender_service.z.so(OHOS::Rosen::RSMainThread::ProcessCommandForDividedRender()1796)
01-01 08:00:14.554 690 690 E C01400/OHOS::RS: #05 pc 0000000000074398 /system/lib64/librender_service.z.so
01-01 08:00:14.554 690 690 E C01400/OHOS::RS: #06 pc 000000000007187c /system/lib64/librender_service.z.so(OHOS::Rosen::RSMainT 3.2 ConsumeAndUpdateAllNodes
这个函数是一个好名字让人一看就知道是干啥的了。我们直接撸代码开始撸代码
//rs_main_thread.cpp
void RSMainThread::ConsumeAndUpdateAllNodes()
{bool needRequestNextVsync false;const auto nodeMap GetContext().GetNodeMap();nodeMap.TraverseSurfaceNodes(//遍历渲染完成的nodemap此处是一个lamda表达式[this, needRequestNextVsync](const std::shared_ptrRSSurfaceRenderNode surfaceNode) mutable {auto surfaceHandler static_castRSSurfaceHandler(*surfaceNode);surfaceHandler.ResetCurrentFrameBufferConsumed();if (RSBaseRenderUtil::ConsumeAndUpdateBuffer(surfaceHandler)) {this-bufferTimestamps_[surfaceNode-GetId()] static_castuint64_t(surfaceNode-GetTimestamp());}// still have buffer(s) to consume.if (surfaceHandler.GetAvailableBufferCount() 0) {needRequestNextVsync true;}});if (needRequestNextVsync) {RequestNextVSync();}
}//rs_base_render_util.cpp
bool RSBaseRenderUtil::ConsumeAndUpdateBuffer(RSSurfaceHandler surfaceHandler)
{auto availableBufferCnt surfaceHandler.GetAvailableBufferCount();if (availableBufferCnt 0) {// this node has no new buffer, try use old buffer.return true;}auto consumer surfaceHandler.GetConsumer();if (consumer nullptr) {return false;}DropFrameProcess(surfaceHandler);sptrSurfaceBuffer buffer;sptrSyncFence acquireFence SyncFence::INVALID_FENCE;int64_t timestamp 0;Rect damage;auto ret consumer-AcquireBuffer(buffer, acquireFence, timestamp, damage);if (buffer nullptr || ret ! SURFACE_ERROR_OK) {RS_LOGE(RsDebug surfaceHandler(id: % PRIu64 ) AcquireBuffer failed(ret: %d)!,surfaceHandler.GetNodeId(), ret);return false;}surfaceHandler.SetBuffer(buffer, acquireFence, damage, timestamp);surfaceHandler.SetCurrentFrameBufferConsumed();RS_LOGD(RsDebug surfaceHandler(id: % PRIu64 ) AcquireBuffer success, timestamp % PRId64 .,surfaceHandler.GetNodeId(), timestamp);availableBufferCnt surfaceHandler.ReduceAvailableBuffer();return true;
}上述代码的核心可以归纳总结为如下两点:
遍历所有的surfacenode然后通过AcquireBuffer获取渲染完成的buffer判断surfacenode是否还有需要消费的buffer如果还有则继续调用RequestNextVSync请求下一次VSync事件 3.3 Render
继续开撸感觉还是一眼望不到头啊。莫停下来继续开搞
void RSMainThread::Render()
{const std::shared_ptrRSBaseRenderNode rootNode context_-GetGlobalRootRenderNode();if (rootNode nullptr) {RS_LOGE(RSMainThread::Render GetGlobalRootRenderNode fail);return;}if (RSSystemProperties::GetRenderNodeTraceEnabled()) {RSPropertyTrace::GetInstance().RefreshNodeTraceInfo();}RS_LOGD(RSMainThread::Render isUni:%d, IfUseUniVisitor());if (IfUseUniVisitor()) {} else {auto rsVisitor std::make_sharedRSRenderServiceVisitor();rsVisitor-SetAnimateState(doWindowAnimate_);rootNode-Prepare(rsVisitor);CalcOcclusion();bool doParallelComposition false;if (!rsVisitor-ShouldForceSerial() RSInnovation::GetParallelCompositionEnabled()) {doParallelComposition DoParallelComposition(rootNode);}if (doParallelComposition) {renderEngine_-ShrinkCachesIfNeeded();return;}rootNode-Process(rsVisitor);}renderEngine_-ShrinkCachesIfNeeded();PerfForBlurIfNeeded();
}/**
继续跟踪rootNode-Process(rsVisitor);
这里的rootNode为std::shared_ptrRSBaseRenderNode globalRootRenderNode_ std::make_sharedRSBaseRenderNode(0, true);
rsVisitor为auto rsVisitor std::make_sharedRSRenderServiceVisitor()我们接着往下看
**/RSBaseRenderNode::Process(...)visitor-ProcessBaseRenderNode(...)//rs_render_service_vistor.cppfor (auto child : node.GetSortedChildren()) {child-Process(shared_from_this());//这个地方是核心}visitor-ProcessSurfaceRenderNode(*this);void RSRenderServiceVisitor::ProcessSurfaceRenderNode(RSSurfaceRenderNode node)
{if (!processor_) {RS_LOGE(RSRenderServiceVisitor::ProcessSurfaceRenderNode processor is nullptr);return;}if (isSecurityDisplay_ node.GetSecurityLayer()) {RS_LOGI(RSRenderServiceVisitor::ProcessSurfaceRenderNode node[% PRIu64 ] process paused because of \security DisplayNode.,node.GetId());return;}if (!node.ShouldPaint()) {RS_LOGD(RSRenderServiceVisitor::ProcessSurfaceRenderNode node : % PRIu64 is invisible, node.GetId());return;}if (!node.GetOcclusionVisible() !doAnimate_ RSSystemProperties::GetOcclusionEnabled()) {return;}if (mParallelEnable) {node.ParallelVisitLock();}ProcessBaseRenderNode(node);node.SetGlobalZOrder(globalZOrder_);globalZOrder_ globalZOrder_ 1;processor_-ProcessSurface(node);//核心点在于这个函数processor_是怎么被初始化的RSBaseRenderUtil::WriteSurfaceRenderNodeToPng(node);//这是一个调试手段将buffer保存成pngif (mParallelEnable) {node.ParallelVisitUnlock();}
}这一块的逻辑主要是将前端gralloc 生成buffer转换成为后端hdi layer供hdi output石永红 3.4 RSProcessor processor_的创建
为了追溯这个问题我倒腾了很久才搞明白创建的流程首先foundatio进程会创建display_render_node然后将其添加到root_node里面去当root_node在进行process处理的时候就会调用到display_render_node中的RSDisplayRenderNode::Prepare和RSDisplayRenderNode::Process最后会调用到RSRenderServiceVisitor::ProcessDisplayRenderNode我们对此展开分析
//rs_render_service_vistor.cpp
void RSRenderServiceVisitor::ProcessDisplayRenderNode(RSDisplayRenderNode node)
{//这里从打印以及调试情况来看RSDisplayRenderNode只有一个每次的id都木有变化isSecurityDisplay_ node.GetSecurityDisplay();RS_LOGD(RsDebug RSRenderServiceVisitor::ProcessDisplayRenderNode: nodeid:[% PRIu64 ] screenid:[% PRIu64 ] \isSecurityDisplay:[%s] child size:[%d] total size:[%d],node.GetId(), node.GetScreenId(), isSecurityDisplay_ ? true : false, node.GetChildrenCount(),node.GetSortedChildren().size());globalZOrder_ 0.0f;sptrRSScreenManager screenManager CreateOrGetScreenManager();if (!screenManager) {RS_LOGE(RSRenderServiceVisitor::ProcessDisplayRenderNode ScreenManager is nullptr);return;}ScreenInfo curScreenInfo screenManager-QueryScreenInfo(node.GetScreenId());RS_TRACE_NAME(ProcessDisplayRenderNode[ std::to_string(node.GetScreenId()) ]);// skip frame according to skipFrameInterval value of SetScreenSkipFrameInterval interfaceif (node.SkipFrame(curScreenInfo.skipFrameInterval)) {return;}//此时创建的是RSPhysicalScreenProcessorprocessor_ RSProcessorFactory::CreateProcessor(node.GetCompositeType());if (processor_ nullptr) {RS_LOGE(RSRenderServiceVisitor::ProcessDisplayRenderNode: RSProcessor is null!);return;}auto mirrorNode node.GetMirrorSource().lock();//详见章节3.4.1if (!processor_-Init(node, node.GetDisplayOffsetX(), node.GetDisplayOffsetY(),mirrorNode ? mirrorNode-GetScreenId() : INVALID_SCREEN_ID)) {RS_LOGE(RSRenderServiceVisitor::ProcessDisplayRenderNode: processor init failed!);return;}if (node.IsMirrorDisplay()) {...} else {ProcessBaseRenderNode(node);}processor_-PostProcess();//详见3.4.2
}3.4.1 RSPhysicalScreenProcessor::Init
分析源码就是烦啊只能fuck you我草草
//rs_physical_screen_processor.cpp
bool RSPhysicalScreenProcessor::Init(RSDisplayRenderNode node, int32_t offsetX, int32_t offsetY, ScreenId mirroredId)
{if (!RSProcessor::Init(node, offsetX, offsetY, mirroredId)) {return false;}if (mirroredId ! INVALID_SCREEN_ID) {SetMirrorScreenSwap(node);}//注意这个地方的回调Redraw很重要当进行GPU合成的时候会调用该回调并且应用到屏幕上面return composerAdapter_-Init(screenInfo_, offsetX, offsetY, mirrorAdaptiveCoefficient_,[this](const auto surface, const auto layers) { Redraw(surface, layers); });
}//rs_composer_adapter.cpp
bool RSComposerAdapter::Init(const ScreenInfo screenInfo, int32_t offsetX, int32_t offsetY,float mirrorAdaptiveCoefficient, const FallbackCallback cb)
{hdiBackend_ HdiBackend::GetInstance();if (hdiBackend_ nullptr) {RS_LOGE(RSComposerAdapter::Init: hdiBackend is nullptr);return false;}auto screenManager CreateOrGetScreenManager();if (screenManager nullptr) {RS_LOGE(RSComposerAdapter::Init: ScreenManager is nullptr);return false;}//获取一个output这个地方得又牵涉到output怎么来的了//screenManager_最开始的初始化是在RsRenderService里面//这里的output表示输出设备output_ screenManager-GetOutput(ToScreenPhysicalId(screenInfo.id));/**bool RSScreenManager::Init() noexcept{//这个地方又牵涉到HdiBackend这个类的实现它的调用逻辑如下:// HdiBackend --- HdiDevice composer_ HdiBackend::GetInstance();if (composer_ nullptr) {RS_LOGE(RSScreenManager %s: Failed to get composer., __func__);return false;}//它的调用逻辑如下:// HdiBackend::RegScreenHotplug// HdiBackend::InitDevice//device_-RegHotPlugCallback(HdiBackend::OnHdiBackendHotPlugEvent, this);// 其中HdiDevice.RegHotPlugCallback// deviceFuncs_-RegHotPlugCallback//HdiSession::GetInstance().RegHotPlugCallback(callback, data);// 主要是drm中的connector//这里的compser搞了忽悠人的名字其实它是HdiBackendif (composer_-RegScreenHotplug(RSScreenManager::OnHotPlug, this) -1) {RS_LOGE(RSScreenManager %s: Failed to register OnHotPlug Func to composer., __func__);return false;}// call ProcessScreenHotPlugEvents() for primary screen immediately in main thread.ProcessScreenHotPlugEvents();return true;}RosenError HdiBackend::InitDevice(){if (device_ ! nullptr) {return ROSEN_ERROR_OK;}device_ HdiDevice::GetInstance();if (device_ nullptr) {HLOGE(Get HdiDevice failed);return ROSEN_ERROR_NOT_INIT;}int32_t ret device_-RegHotPlugCallback(HdiBackend::OnHdiBackendHotPlugEvent, this);if (ret ! DISPLAY_SUCCESS) {HLOGE(RegHotPlugCallback failed, ret is %{public}d, ret);return ROSEN_ERROR_API_FAILED;}HLOGI(Init device succeed);return ROSEN_ERROR_OK;}RosenError HdiBackend::RegScreenHotplug(OnScreenHotplugFunc func, void* data){if (func nullptr) {HLOGE(OnScreenHotplugFunc is null);return ROSEN_ERROR_INVALID_ARGUMENTS;}onScreenHotplugCb_ func;onHotPlugCbData_ data;return InitDevice();}RosenError HdiBackend::InitDevice(){if (device_ ! nullptr) {return ROSEN_ERROR_OK;}device_ HdiDevice::GetInstance();if (device_ nullptr) {HLOGE(Get HdiDevice failed);return ROSEN_ERROR_NOT_INIT;}int32_t ret device_-RegHotPlugCallback(HdiBackend::OnHdiBackendHotPlugEvent, this);if (ret ! DISPLAY_SUCCESS) {HLOGE(RegHotPlugCallback failed, ret is %{public}d, ret);return ROSEN_ERROR_API_FAILED;}HLOGI(Init device succeed);return ROSEN_ERROR_OK;}void HdiBackend::OnHdiBackendHotPlugEvent(uint32_t screenId, bool connected, void *data){HLOGI(HotPlugEvent, screenId is %{public}u, connected is %{public}u, screenId, connected);HdiBackend *hdiBackend nullptr;if (data ! nullptr) {hdiBackend static_castHdiBackend *(data);} else {hdiBackend HdiBackend::GetInstance();}hdiBackend-OnHdiBackendConnected(screenId, connected);}void HdiBackend::OnHdiBackendConnected(uint32_t screenId, bool connected){if (connected) {CreateHdiOutput(screenId);}OnScreenHotplug(screenId, connected);}void HdiBackend::CreateHdiOutput(uint32_t screenId){OutputPtr newOutput HdiOutput::CreateHdiOutput(screenId);newOutput-Init();outputs_.emplace(screenId, newOutput);}std::shared_ptrHdiOutput RSScreenManager::GetOutput(ScreenId id) const{std::lock_guardstd::mutex lock(mutex_);// assert screens_.count(id) 1if (screens_.count(id) 0) {RS_LOGW(RSScreenManager::GetOutput: There is no screen for id % PRIu64 ., id);return nullptr;}//其中screens_调用逻辑老复杂了,通过层层回调/** HdiBackend::OnHdiBackendHotPlugEvent* HdiBackend::OnHdiBackendConnectedHdiBackend::OnHdiBackendConnected* HdiBackend::CreateHdiOutput* OutputPtr newOutput HdiOutput::CreateHdiOutput(screenId);* newOutput-Init();* outputs_.emplace(screenId, newOutput);* HdiBackend::OnScreenHotplug OnScreenHidlConnected(screenId, connected);* onScreenHotplugCb_(...)* RSScreenManager::OnHotPlug(...)* screenManager-OnHotPlugEvent(output, connected)* pendingHotPlugEvents_.emplace_back(ScreenHotPlugEvent{output, connected});* mainThread-RequestNextVSync();//此处会调用ProcessScreenHotPlugEvents()* RSScreenManager::ProcessScreenHotPlugEvents(...)* RSScreenManager::ProcessScreenConnectedLocked(...)* screens_[id] std::make_uniqueRSScreen(id, isVirtual, output, nullptr);** /return screens_.at(id)-GetOutput();}**/if (output_ nullptr) {RS_LOGE(RSComposerAdapter::Init: output_ is nullptr);return false;}fallbackCb_ cb;auto onPrepareCompleteFunc [this](auto surface, const auto param, void* data) {OnPrepareComplete(surface, param, data);};hdiBackend_-RegPrepareComplete(onPrepareCompleteFunc, this);offsetX_ offsetX;offsetY_ offsetY;mirrorAdaptiveCoefficient_ mirrorAdaptiveCoefficient;screenInfo_ screenInfo;IRect damageRect {0, 0, static_castint32_t(screenInfo_.width), static_castint32_t(screenInfo_.height)};output_-SetOutputDamage(1, damageRect);bool directClientCompEnableStatus RSSystemProperties::GetDirectClientCompEnableStatus();output_-SetDirectClientCompEnableStatus(directClientCompEnableStatus);#if (defined RS_ENABLE_GL) (defined RS_ENABLE_EGLIMAGE)// enable direct GPU composition.output_-SetLayerCompCapacity(LAYER_COMPOSITION_CAPACITY);
#else // (defined RS_ENABLE_GL) (defined RS_ENABLE_EGLIMAGE)output_-SetLayerCompCapacity(LAYER_COMPOSITION_CAPACITY_INVALID);
#endif // (defined RS_ENABLE_GL) (defined RS_ENABLE_EGLIMAGE)return true;
}
3.4.2 RSPhysicalScreenProcessor::PostProcess
跟踪代码有点搞谍报工作似的。稍微一不留声代码就不知道溜到那里去了
void RSPhysicalScreenProcessor::PostProcess()
{//这里的核心是这些layers_是怎么来的当然是RSSurfaceRenderNodecomposerAdapter_-CommitLayers(layers_);//详见章节3.5MultiLayersPerf(layers_.size());
}void RSPhysicalScreenProcessor::ProcessSurface(RSSurfaceRenderNode node)
{auto layer composerAdapter_-CreateLayer(node);if (layer nullptr) {RS_LOGD(RSPhysicalScreenProcessor::ProcessSurface: failed to createLayer for node(id: % PRIu64 ), node.GetId());return;}layers_.emplace_back(layer);
}3.5 RSComposerAdapter::CommitLayers
历经磨难我们来到了这里。但是取经的道路还远没有结束战斗还在继续药不能听让我们继续手撕代码
//rs_composer_adapter.cc
void RSComposerAdapter::CommitLayers(const std::vectorLayerInfoPtr layers)
{// do composition.//layers里面只有surfacenode没有displaynode//它接着会调用CreateLayer()output_-SetLayerInfo(layers);std::vectorstd::shared_ptrHdiOutput outputs {output_};hdiBackend_-Repaint(outputs);//详见章节3.7
}//hdi_output.cpp
int32_t HdiOutput::CreateLayer(uint64_t surfaceId, const LayerInfoPtr layerInfo)
{LayerPtr layer HdiLayer::CreateHdiLayer(screenId_);/*** HdiLayer::Init* CreateLayer //hdi_output.cpp* InitDevice()* device_-CreateLayer //hdi_device.cpp* HdiSession::GetInstance().CallDisplayFunction(devId, HdiDisplay::CreateLayer, layerInfo, layerId);//hdi_session.cpp* HdiDisplay::CreateLayer//hdi_display.cpp* **/if (!layer-Init(layerInfo)) {HLOGE(Init hdiLayer failed);return DISPLAY_FAILURE;}layer-UpdateLayerInfo(layerInfo);uint32_t layerId layer-GetLayerId();layerIdMap_[layerId] layer;surfaceIdMap_[surfaceId] layer;return DISPLAY_SUCCESS;
}void HdiOutput::SetLayerInfo(const std::vectorLayerInfoPtr layerInfos)
{for (auto layerInfo : layerInfos) {if (layerInfo nullptr || layerInfo-GetSurface() nullptr) {HLOGE(current layerInfo or layerInfos cSurface is null);continue;}uint64_t surfaceId layerInfo-GetSurface()-GetUniqueId();auto iter surfaceIdMap_.find(surfaceId);if (iter ! surfaceIdMap_.end()) {const LayerPtr layer iter-second;const LayerInfoPtr info layer-GetLayerInfo();if (info-GetLayerSize().w layerInfo-GetLayerSize().w info-GetLayerSize().h layerInfo-GetLayerSize().h){layer-UpdateLayerInfo(layerInfo);continue;}}int32_t ret CreateLayer(surfaceId, layerInfo);if (ret ! DISPLAY_SUCCESS) {return;}}DeletePrevLayers();ResetLayerStatus();
} 3.6 HdiDevice的初始化
本来后续分析的好好的尼玛但是发现这个地方还是跳不过。还是得回来把这个地方分析明白了后续才好继续分析。尼玛
//打印的关于该初始化的相关逻辑
01-01 08:00:10.908 782 782 E C01400/Composer: Init: HdiDevice::Init Tid:782 comm:render_service
01-01 08:00:10.908 782 782 E C01400/Composer: #00 pc 0000000000018ff4 /system/lib64/lib_dfx_dump_catcher.z.so(OHOS::HiviewDFX::DfxDumpCatcher::DumpCatch(int, int, std::__h::basic_stringchar, std::__h::char_traitschar, std::__h::allocatorchar )152)
01-01 08:00:10.908 782 782 E C01400/Composer: #01 pc 0000000000017fd8 /system/lib64/libcomposer.z.so(OHOS::Rosen::HdiDevice::Init()100)
01-01 08:00:10.908 782 782 E C01400/Composer: #02 pc 0000000000017eb4 /system/lib64/libcomposer.z.so(OHOS::Rosen::HdiDevice::GetInstance()72)
01-01 08:00:10.908 782 782 E C01400/Composer: #03 pc 0000000000013b64 /system/lib64/libcomposer.z.so(OHOS::Rosen::HdiBackend::RegScreenHotplug(std::__h::functionvoid (std::__h::shared_ptrOHOS::Rosen::HdiOutput, bool, void*), void*)268)
01-01 08:00:10.908 782 782 E C01400/Composer: #04 pc 00000000000ce50c /system/lib64/librender_service.z.so(OHOS::Rosen::impl::RSScreenManager::Init()88)
01-01 08:00:10.908 782 782 E C01400/Composer: #05 pc 000000000008a6f8 /system/lib64/librender_service.z.so(OHOS::Rosen::RSRenderService::Init()92)
01-01 08:00:10.908 782 782 E C01400/Composer: #06 pc 0000000000006f28 /system/bin/render_service
01-01 08:00:10.908 782 782 E C01400/Composer: #07 pc 00000000000da6f4 /system/lib/ld-musl-aarch64.so.1
01-01 08:00:11.002 782 782 I C01400/Composer: OnHdiBackendHotPlugEvent: HotPlugEvent, screenId is 2, connected is 1
01-01 08:00:11.004 782 782 I C01400/Composer: InitDevice: Init device succeed
01-01 08:00:11.004 782 782 I C01400/Composer: HdiScreen: Create screen, screenId is 2
01-01 08:00:11.026 782 782 E C01400/Composer: Init: HdiDevice::Init Tid:782 comm:render_service
01-01 08:00:11.026 782 782 E C01400/Composer: #00 pc 0000000000018ff4 /system/lib64/lib_dfx_dump_catcher.z.so(OHOS::HiviewDFX::DfxDumpCatcher::DumpCatch(int, int, std::__h::basic_stringchar, std::__h::char_traitschar, std::__h::allocatorchar )152)
01-01 08:00:11.026 782 782 E C01400/Composer: #01 pc 0000000000017fd8 /system/lib64/libcomposer.z.so(OHOS::Rosen::HdiDevice::Init()100)
01-01 08:00:11.026 782 782 E C01400/Composer: #02 pc 0000000000017eb4 /system/lib64/libcomposer.z.so(OHOS::Rosen::HdiDevice::GetInstance()72)
01-01 08:00:11.026 782 782 E C01400/Composer: #03 pc 000000000002d5fc /system/lib64/libcomposer.z.so(OHOS::Rosen::HdiScreen::Init()60)
01-01 08:00:11.026 782 782 E C01400/Composer: #04 pc 00000000000c9644 /system/lib64/librender_service.z.so(OHOS::Rosen::impl::RSScreen::PhysicalScreenInit()116)
01-01 08:00:11.026 782 782 E C01400/Composer: #05 pc 00000000000c959c /system/lib64/librender_service.z.so(OHOS::Rosen::impl::RSScreen::RSScreen(unsigned long, bool, std::__h::shared_ptrOHOS::Rosen::HdiOutput, OHOS::sptrOHOS::Surface)376)
01-01 08:00:11.026 782 782 E C01400/Composer: #06 pc 00000000000ceb48 /system/lib64/librender_service.z.so(OHOS::Rosen::impl::RSScreenManager::ProcessScreenConnectedLocked(std::__h::shared_ptrOHOS::Rosen::HdiOutput
01-01 08:00:11.026 782 782 I C01400/Composer: Init: Init hdiScreen succeed
01-01 08:00:14.504 782 782 I C01400/Composer: Repaint: layer map is empty, drop this frame
01-01 08:00:17.519 782 782 I C01400/Composer: Repaint: layer map is empty, drop this frame
01-01 08:00:20.435 782 782 E C01400/Composer: Init: HdiDevice::Init Tid:782 comm:render_service
01-01 08:00:20.435 782 782 E C01400/Composer: #00 pc 0000000000018ff4 /system/lib64/lib_dfx_dump_catcher.z.so(OHOS::HiviewDFX::DfxDumpCatcher::DumpCatch(int, int, std::__h::basic_stringchar, std::__h::char_traitschar, std::__h::allocatorchar )152)
01-01 08:00:20.435 782 782 E C01400/Composer: #01 pc 0000000000017fd8 /system/lib64/libcomposer.z.so(OHOS::Rosen::HdiDevice::Init()100)
01-01 08:00:20.435 782 782 E C01400/Composer: #02 pc 0000000000017eb4 /system/lib64/libcomposer.z.so(OHOS::Rosen::HdiDevice::GetInstance()72)
01-01 08:00:20.435 782 782 E C01400/Composer: #03 pc 0000000000022674 /system/lib64/libcomposer.z.so(OHOS::Rosen::HdiLayer::CreateLayer(std::__h::shared_ptrOHOS::Rosen::HdiLayerInfo const)68)
01-01 08:00:20.435 782 782 E C01400/Composer: #04 pc 0000000000022610 /system/lib64/libcomposer.z.so(OHOS::Rosen::HdiLayer::Init(std::__h::shared_ptrOHOS::Rosen::HdiLayerInfo const)16)
01-01 08:00:20.435 782 782 E C01400/Composer: #05 pc 0000000000026c88 /system/lib64/libcomposer.z.so(OHOS::Rosen::HdiOutput::CreateLayer(unsigned long, std::__h::shared_ptrOHOS::Rosen::HdiLayerInfo const)68)
01-01 08:00:20.435 782 782 E C01400/Composer: #06 pc 0000000000026bdc /system/lib64/libcomposer.z.so(OHOS::Rosen::HdiOutput::SetLayerInfo(std::__h::vectorstd::__
01-01 08:00:30.950 782 782 E C01400/Composer: Init: HdiDevice::Init Tid:782 comm:render_service
01-01 08:00:30.950 782 782 E C01400/Composer: #00 pc 0000000000018ff4 /system/lib64/lib_dfx_dump_catcher.z.so(OHOS::HiviewDFX::DfxDumpCatcher::DumpCatch(int, int, std::__h::basic_stringchar, std::__h::char_traitschar, std::__h::allocatorchar )152)
01-01 08:00:30.950 782 782 E C01400/Composer: #01 pc 0000000000017fd8 /system/lib64/libcomposer.z.so(OHOS::Rosen::HdiDevice::Init()100)
01-01 08:00:30.950 782 782 E C01400/Composer: #02 pc 0000000000017eb4 /system/lib64/libcomposer.z.so(OHOS::Rosen::HdiDevice::GetInstance()72)
01-01 08:00:30.950 782 782 E C01400/Composer: #03 pc 0000000000022674 /system/lib64/libcomposer.z.so(OHOS::Rosen::HdiLayer::CreateLayer(std::__h::shared_ptrOHOS::Rosen::HdiLayerInfo const)68)
01-01 08:00:30.950 782 782 E C01400/Composer: #04 pc 0000000000022610 /system/lib64/libcomposer.z.so(OHOS::Rosen::HdiLayer::Init(std::__h::shared_ptrOHOS::Rosen::HdiLayerInfo const)16)
01-01 08:00:30.950 782 782 E C01400/Composer: #05 pc 0000000000026c88 /system/lib64/libcomposer.z.so(OHOS::Rosen::HdiOutput::CreateLayer(unsigned long, std::__h::shared_ptrOHOS::Rosen::HdiLayerInfo const)68)
01-01 08:00:30.950 782 782 E C01400/Composer: #06 pc 0000000000026bdc /system/lib64/libcomposer.z.so(OHOS::Rosen::HdiOutput::SetLayerInfo(std::__h::vectorstd::__
01-01 08:00:41.683 782 782 E C01400/Composer: Init: HdiDevice::Init Tid:782 comm:render_service
01-01 08:00:41.683 782 782 E C01400/Composer: #00 pc 0000000000018ff4 /system/lib64/lib_dfx_dump_catcher.z.so(OHOS::HiviewDFX::DfxDumpCatcher::DumpCatch(int, int, std::__h::basic_stringchar, std::__h::char_traitschar, std::__h::allocatorchar )152)
01-01 08:00:41.683 782 782 E C01400/Composer: #01 pc 0000000000017fd8 /system/lib64/libcomposer.z.so(OHOS::Rosen::HdiDevice::Init()100)
01-01 08:00:41.683 782 782 E C01400/Composer: #02 pc 0000000000017eb4 /system/lib64/libcomposer.z.so(OHOS::Rosen::HdiDevice::GetInstance()72)
01-01 08:00:41.683 782 782 E C01400/Composer: #03 pc 0000000000022674 /system/lib64/libcomposer.z.so(OHOS::Rosen::HdiLayer::CreateLayer(std::__h::shared_ptrOHOS::Rosen::HdiLayerInfo const)68)
01-01 08:00:41.683 782 782 E C01400/Composer: #04 pc 0000000000022610 /system/lib64/libcomposer.z.so(OHOS::Rosen::HdiLayer::Init(std::__h::shared_ptrOHOS::Rosen::HdiLayerInfo const)16)
01-01 08:00:41.683 782 782 E C01400/Composer: #05 pc 0000000000026c88 /system/lib64/libcomposer.z.so(OHOS::Rosen::HdiOutput::CreateLayer(unsigned long, std::__h::shared_ptrOHOS::Rosen::HdiLayerInfo const)68)
01-01 08:00:41.683 782 782 E C01400/Composer: #06 pc 0000000000026bdc /system/lib64/libcomposer.z.so(OHOS::Rosen::HdiOutput::SetLayerInfo(std::__h::vectorstd::__//hdi_device.cpp
RosenError HdiDevice::Init()
{/*** * 这里我们可以看出HdiDevice有两个比较重要的钩子* deviceFuncs_和layerFuncs_* 它们的头文件分别是:* drivers/peripheral/display/interfaces/include/display_device.h* drivers/peripheral/display/interfaces/include/display_layer.h* 且这一块的代码都是device或者vendor厂家自己实现了和OpenHarmony关系不大了* **/if (deviceFuncs_ nullptr) {int32_t ret DeviceInitialize(deviceFuncs_);if (ret ! DISPLAY_SUCCESS || deviceFuncs_ nullptr) {HLOGE(DeviceInitialize failed, ret is %{public}d, ret);return ROSEN_ERROR_NOT_INIT;}}if (layerFuncs_ nullptr) {int32_t ret LayerInitialize(layerFuncs_);if (ret ! DISPLAY_SUCCESS || layerFuncs_ nullptr) {Destroy();HLOGE(LayerInitialize failed, ret is %{public}d, ret);return ROSEN_ERROR_NOT_INIT;}}return ROSEN_ERROR_OK;
}extern C {
int32_t DeviceInitialize(DeviceFuncs **funcs)
{DISPLAY_CHK_RETURN((funcs nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE(in funcs is null));DeviceFuncs *dFuncs (DeviceFuncs *)calloc(1, sizeof(DeviceFuncs));DISPLAY_CHK_RETURN((dFuncs nullptr), DISPLAY_FAILURE, DISPLAY_LOGE(can not calloc));dFuncs-RegHotPlugCallback RegHotPlugCallback;dFuncs-GetDisplayCapability GetDisplayCapability;dFuncs-GetDisplaySupportedModes GetDisplaySupportedModes;dFuncs-GetDisplayMode GetDisplayMode;dFuncs-SetDisplayMode SetDisplayMode;dFuncs-GetDisplayPowerStatus GetDisplayPowerStatus;dFuncs-SetDisplayPowerStatus SetDisplayPowerStatus;dFuncs-PrepareDisplayLayers PrepareDisplayLayers;dFuncs-GetDisplayBacklight GetDisplayBacklight;dFuncs-SetDisplayBacklight SetDisplayBacklight;dFuncs-GetDisplayProperty GetDisplayProperty;dFuncs-GetDisplayCompChange GetDisplayCompChange;dFuncs-SetDisplayClientCrop SetDisplayClientCrop;dFuncs-SetDisplayClientDestRect SetDisplayClientDestRect;dFuncs-SetDisplayClientBuffer SetDisplayClientBuffer;dFuncs-SetDisplayClientDamage SetDisplayClientDamage;dFuncs-SetDisplayVsyncEnabled SetDisplayVsyncEnabled;dFuncs-RegDisplayVBlankCallback RegDisplayVBlankCallback;dFuncs-GetDisplayReleaseFence GetDisplayReleaseFence;dFuncs-CreateVirtualDisplay CreateVirtualDisplay;dFuncs-DestroyVirtualDisplay DestroyVirtualDisplay;dFuncs-SetVirtualDisplayBuffer SetVirtualDisplayBuffer;dFuncs-SetDisplayProperty SetDisplayProperty;dFuncs-Commit Commit;*funcs dFuncs;HdiSession::GetInstance();//详见章节3.6.1return DISPLAY_SUCCESS;
}int32_t LayerInitialize(LayerFuncs **funcs)
{DISPLAY_CHK_RETURN((funcs nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE(the in funcs is nullptr));LayerFuncs *lFuncs (LayerFuncs *)calloc(1, sizeof(LayerFuncs));DISPLAY_CHK_RETURN((lFuncs nullptr), DISPLAY_FAILURE, DISPLAY_LOGE(can not calloc errno: %{public}d, errno));lFuncs-SetLayerAlpha SetLayerAlpha;lFuncs-CreateLayer CreateLayer;lFuncs-CloseLayer CloseLayer;lFuncs-SetLayerSize SetLayerSize;lFuncs-SetLayerCrop SetLayerCrop;lFuncs-SetLayerZorder SetLayerZorder;lFuncs-SetLayerPreMulti SetLayerPreMulti;lFuncs-SetTransformMode SetTransformMode;lFuncs-SetLayerDirtyRegion SetLayerDirtyRegion;lFuncs-SetLayerVisibleRegion SetLayerVisibleRegion;lFuncs-SetLayerBuffer SetLayerBuffer;lFuncs-SetLayerCompositionType SetLayerCompositionType;lFuncs-SetLayerBlendType SetLayerBlendType;lFuncs-SetLayerVisible SetLayerVisible;*funcs lFuncs;DISPLAY_LOGD(layer initialize success);return DISPLAY_SUCCESS;
}}3.6.1 HdiSession::GetInstance
干到这里只能一个字形容累。但是累也得继续搞搞搞搞
//hdi_session.cpp
HdiSession HdiSession::GetInstance()
{static HdiSession instance;static std::once_flag once;std::call_once(once, []() { instance.Init(); });return instance;
}void HdiSession::Init()
{DISPLAY_LOGD();//获取一个drmDevicemHdiDevices HdiDeviceInterface::DiscoveryDevice();DISPLAY_LOGD(devices size %{public}zd, mHdiDevices.size());mHdiDisplays.clear();for (auto device : mHdiDevices) {auto displays device-DiscoveryDisplay();mHdiDisplays.insert(displays.begin(), displays.end());}
}//KMS的一些常规操作主要通过libdrm库的API调用来实现。
//drm_device.cpp
std::unordered_mapuint32_t, std::shared_ptrHdiDisplay DrmDevice::DiscoveryDisplay()
{mDisplays.clear();drmModeResPtr res drmModeGetResources(GetDrmFd());DISPLAY_CHK_RETURN((res nullptr), mDisplays, DISPLAY_LOGE(can not get drm resource));// discovery all drm resourceFindAllCrtc(res);FindAllEncoder(res);FindAllConnector(res);FindAllPlane();DISPLAY_LOGD();// travel all connectorfor (auto connectorPair : mConnectors) {auto connector connectorPair.second;uint32_t crtcId 0; int32_t ret;ret connector-PickIdleCrtcId(mEncoders, mCrtcs, crtcId);if (ret ! DISPLAY_SUCCESS) {continue;}DISPLAY_LOGD();auto crtcIter mCrtcs.find(crtcId);if (crtcIter mCrtcs.end()) {DISPLAY_LOGE(can not find crtc for the id %{public}d, connector-GetId());continue;}DISPLAY_LOGD();auto crtc crtcIter-second;DISPLAY_LOGD(crtc %{public}p, crtc.get());// create the displaystd::shared_ptrHdiDisplay display std::make_sharedDrmDisplay(connector, crtc, mInstance);DISPLAY_LOGD();display-Init();//详见章节3.6.2mDisplays.emplace(display-GetId(), std::move(display));}return mDisplays;
}
3.6.2 DrmDisplay::init
猴子的快乐你不懂而我们程序员的快乐你也不懂。但是我懂因为我也是一个
/*** 在源码开始分析前这里我们要知道DrmDisplay继承于HdiDisplay**///drm_display.cpp
int32_t DrmDisplay::Init()
{int ret;DISPLAY_CHK_RETURN((mCrtc nullptr), DISPLAY_FAILURE, DISPLAY_LOGE(crtc is null));DISPLAY_CHK_RETURN((mConnector nullptr), DISPLAY_FAILURE, DISPLAY_LOGE(connector is null));DISPLAY_CHK_RETURN((mDrmDevice nullptr), DISPLAY_FAILURE, DISPLAY_LOGE(drmDevice is null));ret HdiDisplay::Init();DISPLAY_CHK_RETURN((ret ! DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE(init failed));DISPLAY_CHK_RETURN((ret ! DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE(can not init HdiGfxComposition));auto postComp std::make_uniqueHdiDrmComposition(mConnector, mCrtc, mDrmDevice);DISPLAY_CHK_RETURN((postComp nullptr), DISPLAY_FAILURE,DISPLAY_LOGE(can not new HdiDrmComposition errno %{public}d, errno));ret postComp-Init();DISPLAY_CHK_RETURN((ret ! DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE(can not init HdiDrmComposition));/*** HdiDrmComposition继承于HdiComposer* 这里的HdiComposer里的mComposer指向了HdiDrmComposition**/mComposer std::make_uniqueHdiComposer(std::move(postComp));ret mCrtc-BindToDisplay(GetId());DISPLAY_CHK_RETURN((ret ! DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE(bind crtc failed));ret ChosePreferenceMode();DISPLAY_CHK_RETURN((ret ! DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE(choose preference mode fialed));return DISPLAY_SUCCESS;
}3.6.3 小结
通过前面的分析可知我们可以把hdibackend理解为后端其调用逻辑我们可以使用如下的伪代码来表示: HdiBackend ---HdiSession--------HdiDisplay3.7 HdiBackend::Repaint
前途是光明的道路是曲折的。狭路相逢勇者胜木有啥好说的继续撸起袖子干就是了
//hdi_backend.cpp
void HdiBackend::Repaint(std::vectorOutputPtr outputs)
{...int32_t ret DISPLAY_SUCCESS;for (auto output : outputs) {//遍历output通常只有一个输出实例...//获取所有已知ID的Layerconst std::unordered_mapuint32_t, LayerPtr layersMap output-GetLayers();...bool needFlush false;ret PreProcessLayersComp(output, layersMap, needFlush);//详见章节3.8...uint32_t screenId output-GetScreenId();std::vectorLayerPtr compClientLayers;std::vectorLayerInfoPtr newLayerInfos;for (auto iter layersMap.begin(); iter ! layersMap.end(); iter) {const LayerPtr layer iter-second;newLayerInfos.emplace_back(layer-GetLayerInfo());if (layer-GetLayerInfo()-GetCompositionType() GraphicCompositionType::GRAPHIC_COMPOSITION_CLIENT) {compClientLayers.emplace_back(layer);}}if (compClientLayers.size() 0) {needFlush true;HLOGD(Need flush framebuffer, client composition layer num is %{public}zu, compClientLayers.size());}/*** 此时的needFlush为true* **/OnPrepareComplete(needFlush, output, newLayerInfos);//详见章节3.9sptrSurfaceBuffer frameBuffer nullptr;if (needFlush) {/*** 此时的needFlush为truecompClientLayers表示需要通过GPU合成的layers**/if (FlushScreen(output, compClientLayers, frameBuffer) ! DISPLAY_SUCCESS) {//详见章节3.10// return}}sptrSyncFence fbFence SyncFence::INVALID_FENCE;ret device_-Commit(screenId, fbFence);//详见章节3.11...output-UpdatePrevLayerInfo();//交换output中前后buffer...//释放framebufferReleaseFramebuffer(output, fbFence, frameBuffer);lastPresentFence_ fbFence;HLOGD(%{public}s: end, __func__);}
}3.8 HdiDevice::PrepareScreenLayers
辛亏老子以前分析过Android的逻辑代码。不然OpenHarmony里面的各种弯弯绕绕不得搞死人去啊。
//hdi_device.cpp
int32_t HdiDevice::PrepareScreenLayers(uint32_t screenId, bool needFlush)
{CHECK_FUNC(deviceFuncs_, deviceFuncs_-PrepareDisplayLayers);return deviceFuncs_-PrepareDisplayLayers(screenId, needFlush);
}
//此时的needFlushFb为false
//hdi_session.cpp
HdiSession::GetInstance().CallDisplayFunction(devId, HdiDisplay::PrepareDisplayLayers, needFlushFb); //hdi_session.cppHdiDisplay::PrepareDisplayLayers(...)/*** 其中mClientLayer是在HdiDisplay::Init被初始化的* auto layer CreateHdiLayer(LAYER_TYPE_GRAPHIC);* mClientLayer std::move(layer);**/mComposer-Prepare(layers, *mClientLayer)//其中mComposer指向HdiComposer,layers为前面章节3.5 layer-Init传递过来的mPostComp-SetLayers(layers, clientLayer);//hdi_composer.cpp,其中mPostComp指向HdiDrmCompositionHdiDrmComposition::SetLayers(...)for (auto layer : layers) {layer-SetDeviceSelect(COMPOSITION_CLIENT);}mCompLayers.push_back(clientLayer);
PrepareScreenLayers函数的核心功能一句话概括就是对要进行合成的buffer做一些预处理 3.9 HdiBackend::OnPrepareComplete
分析代码真是累啊。搞了一天还没有分析完。革命尚未成功同志还需努力OnPrepareComplete的核心功能为:
主要是对渲染完成的layer进行GPU合成操作并将其写入到FBO中。在合成完成后将FBO写入到屏幕上。
//hdi_backend.cpp
void HdiBackend::OnPrepareComplete(bool needFlush, OutputPtr output, std::vectorLayerInfoPtr newLayerInfos)
{if (needFlush) {ReorderLayerInfo(newLayerInfos);}struct PrepareCompleteParam param {.needFlushFramebuffer needFlush,.layers newLayerInfos,};/*** 这个地方获取的是Surface* 此处的fbSurface_ HdiFramebufferSurface::CreateFramebufferSurface();**//*** SurfaceError HdiFramebufferSurface::CreateSurface(sptrHdiFramebufferSurface fbSurface){consumerSurface_ Surface::CreateSurfaceAsConsumer(FrameBuffer);sptrIBufferProducer producer consumerSurface_-GetProducer();producerSurface_ Surface::CreateSurfaceAsProducer(producer);sptrIBufferConsumerListener listener fbSurface;SurfaceError ret consumerSurface_-RegisterConsumerListener(listener);if (ret ! SURFACE_ERROR_OK) {return SURFACE_ERROR_NO_CONSUMER;}return SURFACE_ERROR_OK;}sptrHdiFramebufferSurface HdiFramebufferSurface::CreateFramebufferSurface(){sptrHdiFramebufferSurface fbSurface new HdiFramebufferSurface();SurfaceError ret fbSurface-CreateSurface(fbSurface);if (ret ! SURFACE_ERROR_OK) {HLOGE(FramebufferSurface CreateSurface failed, ret is %{public}d, ret);return nullptr;}ret fbSurface-SetBufferQueueSize(MAX_BUFFER_SIZE);if (ret ! SURFACE_ERROR_OK) {HLOGE(FramebufferSurface SetBufferQueueSize failed, ret is %{public}d, ret);return nullptr;}return fbSurface;}**/auto fbSurface output-GetFrameBufferSurface();if (onPrepareCompleteCb_ ! nullptr) {//这个地方是个回调函数,它的执行逻辑如下/**onPrepareCompleteCb_(...)//hdi_backend.cpp* RSComposerAdapter::OnPrepareComplete(...)//rs_composer_adapter.cpp* RSPhysicalScreenProcessor::Redraw(...)//rs_physical_screen_processor.cpp详见章节3.9.1**/onPrepareCompleteCb_(fbSurface, param, onPrepareCompleteCbData_);}
}
3.9.1 RSPhysicalScreenProcessor::Redraw
继续执行RSComposerAdapter::OnPrepareComplete函数将其传递到rs_physical_screen_processor.cpp中。 在rs_physical_screen_processor.cpp中执行RSPhysicalScreenProcessor::Redraw函数。
//rs_physical_screen_processor.cpp
void RSPhysicalScreenProcessor::Redraw(const sptrSurface surface, const std::vectorLayerInfoPtr layers)
{RS_TRACE_NAME(Redraw);//此处的流程和bootamition中的何其相似RS_LOGD(RsDebug RSPhysicalScreenProcessor::Redraw flush frame buffer start);bool forceCPU RSBaseRenderEngine::NeedForceCPU(layers);auto renderFrame renderEngine_-RequestFrame(surface, renderFrameConfig_, forceCPU);auto canvas renderFrame-GetCanvas();if (canvas nullptr) {RS_LOGE(RsDebug RSPhysicalScreenProcessor::Redrawcanvas is nullptr.);return;}canvas-concat(screenTransformMatrix_);//此处的forceCPU为falserenderEngine_为rs_render_engine.cpp中的一个引用renderEngine_-DrawLayers(*canvas, layers, forceCPU, mirrorAdaptiveCoefficient_);/*** 此处调用surface的flaush然后触发HdiFramebufferSurface::OnBufferAvailable()* 详见章节3.9.2**/renderFrame-Flush();RS_LOGD(RsDebug RSPhysicalScreenProcessor::Redraw flush frame buffer end);
}3.9.2 HdiFramebufferSurface::OnBufferAvailable
兜兜转转一路走来。不容易既然选择了那就干就是了。坚信自己是最牛逼的
//hdi_framebuffer_surface.cpp
void HdiFramebufferSurface::OnBufferAvailable()
{sptrSurfaceBuffer buffer;int64_t timestamp 0;Rect damage {0};sptrSyncFence acquireFence SyncFence::INVALID_FENCE;//获取可用bufferSurfaceError ret consumerSurface_-AcquireBuffer(buffer, acquireFence,timestamp, damage);if (ret ! SURFACE_ERROR_OK || buffer nullptr) {HLOGE(AcquireBuffer failed, ret is %{public}d, ret);return;}std::lock_guardstd::mutex lock(mutex_);//放入availableBuffers_.push(std::make_uniqueFrameBufferEntry(buffer, acquireFence, timestamp, damage));bufferCond_.notify_one();//唤醒等待
}总结上述代码的核心逻辑就是:
消费前面的合成后图层的buffer并放入AvailableBuffers_中然后唤醒bufferCond_等待事件 3.10 HdiBackend::FlushScreen
离成功越来越近了再坚持一把冲一冲前途是美好的未来是光明的道路是曲折的。此时不拼搏更待何时
//hdi_backend.cpp
int32_t HdiBackend::FlushScreen(const OutputPtr output, std::vectorLayerPtr compClientLayers, sptrSurfaceBuffer buffer)
{//获取前面合成好的图层bufferauto fbEntry output-GetFramebuffer();const auto fbAcquireFence fbEntry-acquireFence;for (auto layer : compClientLayers) {layer-MergeWithFramebufferFence(fbAcquireFence);//这个地方没有看出来有啥用}buffer fbEntry-buffer;return SetScreenClientInfo(*fbEntry, output);//继续接着往下看3.10.1
}3.10.1 HdiBackend::SetScreenClientInfo
别人说见色起意这里我们见名思意。这个函数是干嘛的呢我们一道来分析
//hdi_backend.cpp
int32_t HdiBackend::SetScreenClientInfo(const OutputPtr output, const OutputPtr clientOutput)
{if (buffer nullptr) {return;}if (lastFrameBuffers_.find(output-GetScreenId()) ! lastFrameBuffers_.end()) {// wrong check(void)output-ReleaseFramebuffer(lastFrameBuffers_[output-GetScreenId()], presentFence);}lastFrameBuffers_[output-GetScreenId()] buffer;
}int32_t HdiBackend::SetScreenClientInfo(const FrameBufferEntry fbEntry, const OutputPtr output)
{.../*** 设置上屏buffer,它的调用逻辑如下:* HdiDevice::SetScreenClientBuffer* SetDisplayClientBuffer(...)//hdi_session.cpp* HdiDisplay::SetDisplayClientBuffer()//hdi_display.cpp* mClientLayer-SetLayerBuffer(buffer, fence)//这里的mClientLayer是在hdi_display在init中被初始化的但是没有提供buffer实质性的内容* std::unique_ptrHdiLayerBuffer layerbuffer std::make_uniqueHdiLayerBuffer(*buffer);* mHdiBuffer std::move(layerbuffer)**/int ret device_-SetScreenClientBuffer(output-GetScreenId(),fbEntry.buffer-GetBufferHandle(), fbEntry.acquireFence);//这个函数毛都木有做ret device_-SetScreenClientDamage(output-GetScreenId(), output-GetOutputDamageNum(),output-GetOutputDamage());...return DISPLAY_SUCCESS;
}3.10.2 小结
FlushScreen的核心功能可以概括为:
将合成OK之后的图层送到hdioupt接着送往hdidisplay等待显示 3.11 HdiDevice::Commit
前面的铺垫都是为了最后将图层应用到屏幕上而此处便是最后一搏了单车能否变摩托!
//hdi_device.cpp
int32_t HdiDevice::Commit(uint32_t screenId, sptrSyncFence fence)
{...int32_t ret deviceFuncs_-Commit(screenId, fenceFd);...return ret;
}/*** 其中deviceFuncs_-Commit的调用逻辑如下:* Commit(...)//hdi_session.cpp* HdiSession::GetInstance().CallDisplayFunction(devId, HdiDisplay::Commit, fence)* HdiDisplay::Commit(...)//hdi_display.cpp* mComposer-Commit(false)//hdi_composer.cpp* mPostComp-Apply(modeSet)//hdi_drm_composition.cpp* 接下来就是一番drm送显示的一番常规操作了**/ 写在最后 到这里OpenHarmony送显流程分析介绍就告一段落了!编写该文档的过程我也是小心再小心谨慎再谨慎但是难免其中可能会有一些概念或者理论不对这个希望各位能多多指针就我分析个人感觉OH的很多理念都是和Android非常相似基本只是换了一套实现而已。看来OpenHarmony还有很长的路要走大路漫漫其修吾将上下而求索总之青山不改绿水长流先到这里了各位江湖见由于本人也是接触OpenHarmony不是很长时间各位大大勿喷 其中涉及的一些私有代码参见仓库 Phytium嵌入式软件 / Phytium-OpenHarmony-D2000-X100