• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "rs_hardware_thread.h"
17 
18 #include <memory>
19 #include <unistd.h>
20 
21 #include "frame_report.h"
22 #include "hdi_backend.h"
23 #include "hgm_frame_rate_manager.h"
24 #include "hisysevent.h"
25 #include "parameters.h"
26 #include "pipeline/hardware_thread/rs_realtime_refresh_rate_manager.h"
27 #include "rs_trace.h"
28 #include "vsync_sampler.h"
29 
30 #include "common/rs_exception_check.h"
31 #include "common/rs_optional_trace.h"
32 #include "common/rs_singleton.h"
33 #include "feature/hdr/rs_hdr_util.h"
34 #include "feature/round_corner_display/rs_round_corner_display_manager.h"
35 #include "pipeline/render_thread/rs_base_render_util.h"
36 #include "pipeline/main_thread/rs_main_thread.h"
37 #include "pipeline/render_thread/rs_uni_render_engine.h"
38 #include "pipeline/render_thread/rs_uni_render_thread.h"
39 #include "pipeline/render_thread/rs_uni_render_util.h"
40 #include "platform/common/rs_log.h"
41 #include "platform/common/rs_system_properties.h"
42 #include "platform/ohos/backend/rs_surface_ohos_gl.h"
43 #include "platform/ohos/backend/rs_surface_ohos_raster.h"
44 #include "screen_manager/rs_screen_manager.h"
45 #include "gfx/fps_info/rs_surface_fps_manager.h"
46 #include "gfx/first_frame_notifier/rs_first_frame_notifier.h"
47 #include "platform/common/rs_hisysevent.h"
48 #include "graphic_feature_param_manager.h"
49 
50 #ifdef RS_ENABLE_EGLIMAGE
51 #ifdef USE_M133_SKIA
52 #include "src/gpu/ganesh/gl/GrGLDefines.h"
53 #else
54 #include "src/gpu/gl/GrGLDefines.h"
55 #endif
56 #endif
57 
58 #ifdef RS_ENABLE_VK
59 #include "platform/ohos/backend/rs_surface_ohos_vulkan.h"
60 #include "feature/gpuComposition/rs_vk_image_manager.h"
61 #endif
62 
63 #ifdef RS_ENABLE_EGLIMAGE
64 #include "feature/gpuComposition/rs_egl_image_manager.h"
65 #endif // RS_ENABLE_EGLIMAGE
66 
67 #ifdef USE_VIDEO_PROCESSING_ENGINE
68 #include "metadata_helper.h"
69 #endif
70 
71 #ifdef RES_SCHED_ENABLE
72 #include "system_ability_definition.h"
73 #include "if_system_ability_manager.h"
74 #include <iservice_registry.h>
75 #include "ressched_event_listener.h"
76 #endif
77 
78 #ifdef RS_ENABLE_TV_PQ_METADATA
79 #include "feature/tv_metadata/rs_tv_metadata_manager.h"
80 #endif
81 
82 #undef LOG_TAG
83 #define LOG_TAG "RSHardwareThread"
84 
85 namespace OHOS::Rosen {
86 namespace {
87 constexpr uint32_t HARDWARE_THREAD_TASK_NUM = 2;
88 constexpr uint32_t HARD_JANK_TWO_TIME = 2;
89 constexpr int64_t REFRESH_PERIOD = 16667; // 16667us == 16.667ms
90 constexpr int64_t REPORT_LOAD_WARNING_INTERVAL_TIME = 5000000; // 5s == 5000000us
91 constexpr int64_t RESERVE_TIME = 1000000; // we reserve 1ms more for the composition
92 constexpr int64_t COMMIT_DELTA_TIME = 2; // 2ms
93 constexpr int64_t MAX_DELAY_TIME = 100; // 100ms
94 constexpr int64_t NS_MS_UNIT_CONVERSION = 1000000;
95 constexpr int64_t UNI_RENDER_VSYNC_OFFSET_DELAY_MODE = 3300000; // 3.3ms
96 constexpr uint32_t MAX_TOTAL_SURFACE_NAME_LENGTH = 320;
97 constexpr uint32_t MAX_SINGLE_SURFACE_NAME_LENGTH = 20;
98 // Threshold for abnormal time in the hardware pipeline
99 constexpr int HARDWARE_TIMEOUT = 800;
100 // The number of exceptions in the hardware pipeline required to achieve render_service reset
101 constexpr int HARDWARE_TIMEOUT_ABORT_CNT = 30;
102 // The number of exceptions in the hardware pipeline required to report hisysevent
103 constexpr int HARDWARE_TIMEOUT_CNT = 15;
104 const std::string PROCESS_NAME_FOR_HISYSEVENT = "/system/bin/render_service";
105 const std::string HARDWARE_PIPELINE_TIMEOUT = "hardware_pipeline_timeout";
106 }
107 
SystemTime()108 static int64_t SystemTime()
109 {
110     timespec t = {};
111     clock_gettime(CLOCK_MONOTONIC, &t);
112     return int64_t(t.tv_sec) * 1000000000LL + t.tv_nsec; // 1000000000ns == 1s
113 }
114 
Instance()115 RSHardwareThread& RSHardwareThread::Instance()
116 {
117     static RSHardwareThread instance;
118     return instance;
119 }
120 
Start()121 void RSHardwareThread::Start()
122 {
123     RS_LOGI("Start()!");
124     hdiBackend_ = HdiBackend::GetInstance();
125     runner_ = AppExecFwk::EventRunner::Create("RSHardwareThread");
126     handler_ = std::make_shared<AppExecFwk::EventHandler>(runner_);
127     redrawCb_ = [this](const sptr<Surface>& surface, const std::vector<LayerInfoPtr>& layers, uint32_t screenId) {
128         return this->Redraw(surface, layers, screenId);
129     };
130     if (handler_) {
131         ScheduleTask([this]() {
132 #if defined (RS_ENABLE_VK)
133             // Change vk interface type from UNIRENDER into UNPROTECTED_REDRAW, this is necessary for hardware init.
134             if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
135                 RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
136                 RsVulkanContext::GetSingleton().SetIsProtected(false);
137             }
138 #endif
139             auto screenManager = CreateOrGetScreenManager();
140             if (screenManager == nullptr || !screenManager->Init()) {
141                 RS_LOGE("RSHardwareThread CreateOrGetScreenManager or init fail.");
142                 return;
143             }
144 #ifdef RES_SCHED_ENABLE
145             SubScribeSystemAbility();
146 #endif
147             uniRenderEngine_ = std::make_shared<RSUniRenderEngine>();
148             uniRenderEngine_->Init();
149             // posttask for multithread safely release surface and image
150             ContextRegisterPostTask();
151             hardwareTid_ = gettid();
152         }).wait();
153     }
154     auto onPrepareCompleteFunc = [this](auto& surface, const auto& param, void* data) {
155         OnPrepareComplete(surface, param, data);
156     };
157     if (hdiBackend_ != nullptr) {
158         hdiBackend_->RegPrepareComplete(onPrepareCompleteFunc, this);
159     }
160 }
161 
GetHardwareTid() const162 int RSHardwareThread::GetHardwareTid() const
163 {
164     return hardwareTid_;
165 }
166 
PostTask(const std::function<void ()> & task)167 void RSHardwareThread::PostTask(const std::function<void()>& task)
168 {
169     if (handler_) {
170         handler_->PostTask(task, AppExecFwk::EventQueue::Priority::IMMEDIATE);
171     }
172 }
173 
PostSyncTask(const std::function<void ()> & task)174 void RSHardwareThread::PostSyncTask(const std::function<void()>& task)
175 {
176     if (handler_) {
177         handler_->PostSyncTask(task, AppExecFwk::EventQueue::Priority::IMMEDIATE);
178     }
179 }
180 
PostDelayTask(const std::function<void ()> & task,int64_t delayTime)181 void RSHardwareThread::PostDelayTask(const std::function<void()>& task, int64_t delayTime)
182 {
183     if (handler_) {
184         handler_->PostTask(task, delayTime, AppExecFwk::EventQueue::Priority::IMMEDIATE);
185     }
186 }
187 
DumpVkImageInfo(std::string & dumpString)188 void RSHardwareThread::DumpVkImageInfo(std::string &dumpString)
189 {
190     std::weak_ptr<RSBaseRenderEngine> uniRenderEngine = uniRenderEngine_;
191     PostSyncTask([&dumpString, uniRenderEngine]() {
192         if (auto engine = uniRenderEngine.lock()) {
193             engine->DumpVkImageInfo(dumpString);
194         }
195     });
196 }
197 
GetunExecuteTaskNum()198 uint32_t RSHardwareThread::GetunExecuteTaskNum()
199 {
200     return unExecuteTaskNum_.load();
201 }
202 
ClearRedrawGPUCompositionCache(const std::set<uint32_t> & bufferIds)203 void RSHardwareThread::ClearRedrawGPUCompositionCache(const std::set<uint32_t>& bufferIds)
204 {
205     std::weak_ptr<RSBaseRenderEngine> uniRenderEngine = uniRenderEngine_;
206     PostDelayTask(
207         [uniRenderEngine, bufferIds]() {
208             if (auto engine = uniRenderEngine.lock()) {
209                 engine->ClearCacheSet(bufferIds);
210             }
211         },
212         delayTime_);
213 }
214 
RefreshRateCounts(std::string & dumpString)215 void RSHardwareThread::RefreshRateCounts(std::string& dumpString)
216 {
217     if (refreshRateCounts_.empty()) {
218         RS_LOGE("RefreshData fail, refreshRateCounts_ is empty");
219         return;
220     }
221     std::map<uint32_t, uint64_t>::iterator iter;
222     for (iter = refreshRateCounts_.begin(); iter != refreshRateCounts_.end(); ++iter) {
223         dumpString.append(
224             "Refresh Rate:" + std::to_string(iter->first) + ", Count:" + std::to_string(iter->second) + ";\n");
225     }
226     RS_LOGD("RefreshRateCounts refresh rate counts info is displayed");
227 }
228 
ClearRefreshRateCounts(std::string & dumpString)229 void RSHardwareThread::ClearRefreshRateCounts(std::string& dumpString)
230 {
231     if (refreshRateCounts_.empty()) {
232         RS_LOGE("ClearRefreshData fail, refreshRateCounts_ is empty");
233         return;
234     }
235     refreshRateCounts_.clear();
236     dumpString.append("The refresh rate counts info is cleared successfully!\n");
237     RS_LOGD("RefreshRateCounts refresh rate counts info is cleared");
238 }
239 
CommitAndReleaseLayers(OutputPtr output,const std::vector<LayerInfoPtr> & layers)240 void RSHardwareThread::CommitAndReleaseLayers(OutputPtr output, const std::vector<LayerInfoPtr>& layers)
241 {
242     if (!handler_) {
243         RS_LOGE("CommitAndReleaseLayers handler is nullptr");
244         return;
245     }
246     delayTime_ = 0;
247     RSTimer timer("Hardware", HARDWARE_TIMEOUT);
248     LayerComposeCollection::GetInstance().UpdateUniformOrOfflineComposeFrameNumberForDFX(layers.size());
249     hgmHardwareUtils_.UpdateRefreshRateParam();
250     RefreshRateParam param = hgmHardwareUtils_.GetRefreshRateParam();
251     auto& hgmCore = OHOS::Rosen::HgmCore::Instance();
252     ScreenId curScreenId = hgmCore.GetActiveScreenId();
253     uint32_t currentRate = hgmCore.GetScreenCurrentRefreshRate(curScreenId);
254     bool hasGameScene = FrameReport::GetInstance().HasGameScene();
255 #ifdef RES_SCHED_ENABLE
256     ResschedEventListener::GetInstance()->ReportFrameToRSS();
257 #endif
258     RSTaskMessage::RSTask task = [this, output = output, layers = layers, param = param,
259         currentRate = currentRate, hasGameScene = hasGameScene, curScreenId = curScreenId]() {
260 #ifdef HIPERF_TRACE_ENABLE
261         RS_LOGW("hiperf_surface_counter3 %{public}" PRIu64 " ", static_cast<uint64_t>(layers.size()));
262 #endif
263         int64_t startTime = GetCurTimeCount();
264         std::string surfaceName = GetSurfaceNameInLayers(layers);
265         RS_LOGD("CommitAndReleaseLayers task execute, %{public}s", surfaceName.c_str());
266         if (output == nullptr || hdiBackend_ == nullptr) {
267             RS_LOGI("CommitAndReleaseLayers task return, %{public}s", surfaceName.c_str());
268             return;
269         }
270         int64_t startTimeNs = 0;
271         int64_t endTimeNs = 0;
272 
273         RSFirstFrameNotifier::GetInstance().ExecIfFirstFrameCommit(output->GetScreenId());
274 
275         RS_LOGI_IF(DEBUG_COMPOSER, "CommitAndReleaseData hasGameScene is %{public}d %{public}s",
276             hasGameScene, surfaceName.c_str());
277         if (hasGameScene) {
278             startTimeNs = std::chrono::duration_cast<std::chrono::nanoseconds>(
279                 std::chrono::steady_clock::now().time_since_epoch()).count();
280         }
281         RS_TRACE_NAME_FMT("CommitLayers rate:%u,now:%" PRIu64 ",vsyncId:%" PRIu64 ",size:%zu,%s",
282             currentRate, param.frameTimestamp, param.vsyncId, layers.size(),
283             GetSurfaceNameInLayersForTrace(layers).c_str());
284         RS_LOGD("CommitLayers rate:%{public}u, now:%{public}" PRIu64 ",vsyncId:%{public}" PRIu64 ", \
285             size:%{public}zu, %{public}s", currentRate, param.frameTimestamp, param.vsyncId, layers.size(),
286             GetSurfaceNameInLayersForTrace(layers).c_str());
287         bool isScreenPoweringOff = false;
288         auto screenManager = CreateOrGetScreenManager();
289         if (screenManager) {
290             isScreenPoweringOff = RSSystemProperties::IsSmallFoldDevice() &&
291                 screenManager->IsScreenPoweringOff(output->GetScreenId());
292         }
293 
294         bool shouldDropFrame = isScreenPoweringOff || IsDropDirtyFrame(layers, output->GetScreenId());
295         if (!shouldDropFrame) {
296             hgmHardwareUtils_.ExecuteSwitchRefreshRate(output, param.rate);
297             hgmHardwareUtils_.PerformSetActiveMode(
298                 output, param.frameTimestamp, param.constraintRelativeTime);
299             AddRefreshRateCount(output);
300         }
301 
302         if (RSSystemProperties::IsSuperFoldDisplay() && output->GetScreenId() == 0) {
303             std::vector<LayerInfoPtr> reviseLayers = layers;
304             ChangeLayersForActiveRectOutside(reviseLayers, curScreenId);
305             output->SetLayerInfo(reviseLayers);
306         } else {
307             output->SetLayerInfo(layers);
308         }
309         bool doRepaint = output->IsDeviceValid() && !shouldDropFrame;
310         if (doRepaint) {
311             hdiBackend_->Repaint(output);
312             RecordTimestamp(layers);
313         }
314         output->ReleaseLayers(releaseFence_);
315         RSBaseRenderUtil::DecAcquiredBufferCount();
316         RSUniRenderThread::Instance().NotifyScreenNodeBufferReleased();
317         if (hasGameScene) {
318             endTimeNs = std::chrono::duration_cast<std::chrono::nanoseconds>(
319                 std::chrono::steady_clock::now().time_since_epoch()).count();
320             FrameReport::GetInstance().SetLastSwapBufferTime(endTimeNs - startTimeNs);
321         }
322 
323         unExecuteTaskNum_--;
324         RS_LOGD_IF(DEBUG_COMPOSER, "CommitAndReleaseData unExecuteTaskNum_:%{public}d,"
325             " HARDWARE_THREAD_TASK_NUM:%{public}d, %{public}s",
326             unExecuteTaskNum_.load(), HARDWARE_THREAD_TASK_NUM, surfaceName.c_str());
327         if (unExecuteTaskNum_ <= HARDWARE_THREAD_TASK_NUM) {
328             RSMainThread::Instance()->NotifyHardwareThreadCanExecuteTask();
329         }
330         RSMainThread::Instance()->SetTaskEndWithTime(SystemTime() - lastActualTime_);
331         lastActualTime_ = param.actualTimestamp;
332         int64_t endTime = GetCurTimeCount();
333         uint64_t frameTime = endTime - startTime;
334         uint32_t missedFrames = frameTime / REFRESH_PERIOD;
335         uint16_t frameRate = currentRate;
336         if (missedFrames >= HARD_JANK_TWO_TIME &&
337             endTime - intervalTimePoints_ > REPORT_LOAD_WARNING_INTERVAL_TIME) {
338             RS_LOGI("CommitAndReleaseLayers report load event frameTime: %{public}" PRIu64
339                 " missedFrame: %{public}" PRIu32 " frameRate:%{public}" PRIu16 " %{public}s",
340                 frameTime, missedFrames, frameRate, surfaceName.c_str());
341             intervalTimePoints_ = endTime;
342             RS_TRACE_NAME("RSHardwareThread::CommitAndReleaseLayers HiSysEventWrite in RSHardwareThread");
343             RSHiSysEvent::EventWrite(RSEventName::RS_HARDWARE_THREAD_LOAD_WARNING, RSEventType::RS_STATISTIC,
344                 "FRAME_RATE", frameRate, "MISSED_FRAMES", missedFrames, "FRAME_TIME", frameTime);
345         }
346     };
347     RSBaseRenderUtil::IncAcquiredBufferCount();
348     unExecuteTaskNum_++;
349     RSMainThread::Instance()->SetHardwareTaskNum(unExecuteTaskNum_.load());
350     RS_LOGI_IF(DEBUG_COMPOSER, "CommitAndReleaseData hgmCore's LtpoEnabled is %{public}d", hgmCore.GetLtpoEnabled());
351     int64_t currTime = SystemTime();
352     if (IsDelayRequired(hgmCore, param, output, hasGameScene)) {
353         CalculateDelayTime(hgmCore, param, currentRate, currTime);
354     }
355 
356     // We need to ensure the order of composition frames, postTaskTime(n + 1) must > postTaskTime(n),
357     // and we give a delta time more between two composition tasks.
358     int64_t currCommitTime = currTime + delayTime_ * NS_MS_UNIT_CONVERSION;
359     if (currCommitTime <= lastCommitTime_) {
360         delayTime_ = delayTime_ +
361             std::round((lastCommitTime_ - currCommitTime) * 1.0f / NS_MS_UNIT_CONVERSION) +
362             COMMIT_DELTA_TIME;
363         RS_LOGD("CommitAndReleaseLayers vsyncId: %{public}" PRIu64 ", " \
364             "update delayTime: %{public}" PRId64 ", currCommitTime: %{public}" PRId64 ", " \
365             "lastCommitTime: %{public}" PRId64, param.vsyncId, delayTime_, currCommitTime, lastCommitTime_);
366         RS_TRACE_NAME_FMT("update delayTime: %" PRId64 ", currCommitTime: %" PRId64 ", lastCommitTime: %" PRId64 "",
367             delayTime_, currCommitTime, lastCommitTime_);
368     }
369     if (delayTime_ < 0 || delayTime_ >= MAX_DELAY_TIME) {
370         delayTime_ = 0;
371     }
372     lastCommitTime_ = currTime + delayTime_ * NS_MS_UNIT_CONVERSION;
373     EndCheck(timer);
374     PostDelayTask(task, delayTime_);
375 }
376 
EndCheck(RSTimer timer)377 void RSHardwareThread::EndCheck(RSTimer timer)
378 {
379     exceptionCheck_.pid_ = getpid();
380     exceptionCheck_.uid_ = getuid();
381     exceptionCheck_.processName_ = PROCESS_NAME_FOR_HISYSEVENT;
382     exceptionCheck_.exceptionPoint_ = HARDWARE_PIPELINE_TIMEOUT;
383 
384     if (timer.GetDuration() >= HARDWARE_TIMEOUT) {
385         if (++hardwareCount_ == HARDWARE_TIMEOUT_CNT) {
386             RS_LOGE("Hardware Thread Exception Count[%{public}d]", hardwareCount_);
387             exceptionCheck_.exceptionCnt_ = hardwareCount_;
388             exceptionCheck_.exceptionMoment_ = timer.GetSeconds();
389             exceptionCheck_.UploadRenderExceptionData();
390         }
391     } else {
392         hardwareCount_ = 0;
393     }
394     if (hardwareCount_ == HARDWARE_TIMEOUT_ABORT_CNT) {
395         exceptionCheck_.exceptionCnt_ = hardwareCount_;
396         exceptionCheck_.exceptionMoment_ = timer.GetSeconds();
397         exceptionCheck_.UploadRenderExceptionData();
398         RS_LOGE("RSHardwareThread::EndCheck PID:%{public}d, UID:%{public}u, PROCESS_NAME:%{public}s, \
399             EXCEPTION_CNT:%{public}d, EXCEPTION_TIME:%{public}" PRId64", EXCEPTION_POINT:%{public}s",
400             getpid(), getuid(), PROCESS_NAME_FOR_HISYSEVENT.c_str(), hardwareCount_,
401             exceptionCheck_.exceptionMoment_, HARDWARE_PIPELINE_TIMEOUT.c_str());
402     }
403 }
404 
ChangeLayersForActiveRectOutside(std::vector<LayerInfoPtr> & layers,ScreenId screenId)405 void RSHardwareThread::ChangeLayersForActiveRectOutside(std::vector<LayerInfoPtr>& layers, ScreenId screenId)
406 {
407 #ifdef ROSEN_EMULATOR
408     RS_LOGD("emulator device do not need add layer");
409     return;
410 #endif
411     if (!RSSystemProperties::IsSuperFoldDisplay() || layers.size() == 0) {
412         return;
413     }
414     auto screenManager = CreateOrGetScreenManager();
415     if (!screenManager) {
416         return;
417     }
418     auto screenInfo = screenManager->QueryScreenInfo(screenId);
419     const RectI& reviseRect = screenInfo.reviseRect;
420     if (reviseRect.width_ <= 0 || reviseRect.height_ <= 0) {
421         return;
422     }
423     const RectI& maskRect = screenInfo.maskRect;
424     if (maskRect.width_ > 0 && maskRect.height_ > 0) {
425         auto solidColorLayer = HdiLayerInfo::CreateHdiLayerInfo();
426         solidColorLayer->SetZorder(INT_MAX - 1);
427         solidColorLayer->SetTransform(GraphicTransformType::GRAPHIC_ROTATE_NONE);
428         GraphicIRect dstRect = {maskRect.left_, maskRect.top_, maskRect.width_, maskRect.height_};
429         solidColorLayer->SetLayerSize(dstRect);
430         solidColorLayer->SetIsMaskLayer(true);
431         solidColorLayer->SetCompositionType(GraphicCompositionType::GRAPHIC_COMPOSITION_SOLID_COLOR);
432         bool debugFlag = (system::GetParameter("debug.foldscreen.shaft.color", "0") == "1");
433         if (debugFlag) {
434             solidColorLayer->SetLayerColor({0, 255, 0, 255});
435         } else {
436             solidColorLayer->SetLayerColor({0, 0, 0, 255});
437         }
438         layers.emplace_back(solidColorLayer);
439     }
440     using RSRcdManager = RSSingleton<RoundCornerDisplayManager>;
441     for (auto& layerInfo : layers) {
442         auto layerSurface = layerInfo->GetSurface();
443         if (layerSurface != nullptr) {
444             auto rcdlayerInfo = RSRcdManager::GetInstance().GetLayerPair(layerSurface->GetName());
445             if (rcdlayerInfo.second != RoundCornerDisplayManager::RCDLayerType::INVALID) {
446                 continue;
447             }
448         }
449         GraphicIRect dstRect = layerInfo->GetLayerSize();
450         GraphicIRect tmpRect = dstRect;
451         int reviseRight = reviseRect.left_ + reviseRect.width_;
452         int reviseBottom = reviseRect.top_ + reviseRect.height_;
453         tmpRect.x = std::clamp(dstRect.x, reviseRect.left_, reviseRight);
454         tmpRect.y = std::clamp(dstRect.y, reviseRect.top_, reviseBottom);
455         tmpRect.w = std::min(tmpRect.x + dstRect.w, reviseRight) - tmpRect.x;
456         tmpRect.h = std::min(tmpRect.y + dstRect.h, reviseBottom) - tmpRect.y;
457         layerInfo->SetLayerSize(tmpRect);
458     }
459 }
460 
GetSurfaceNameInLayers(const std::vector<LayerInfoPtr> & layers)461 std::string RSHardwareThread::GetSurfaceNameInLayers(const std::vector<LayerInfoPtr>& layers)
462 {
463     std::string surfaceName = "SurfaceName: [";
464     bool isFirst = true;
465     for (const auto& layer : layers) {
466         if (layer == nullptr || layer->GetSurface() == nullptr) {
467             continue;
468         }
469         if (isFirst) {
470             surfaceName += layer->GetSurface()->GetName();
471             isFirst = false;
472             continue;
473         }
474         surfaceName += ", " + layer->GetSurface()->GetName();
475     }
476     surfaceName += "]";
477     return surfaceName;
478 }
479 
GetSurfaceNameInLayersForTrace(const std::vector<LayerInfoPtr> & layers)480 std::string RSHardwareThread::GetSurfaceNameInLayersForTrace(const std::vector<LayerInfoPtr>& layers)
481 {
482     uint32_t count = layers.size();
483     uint32_t max = 0;
484     for (const auto& layer : layers) {
485         if (layer == nullptr || layer->GetSurface() == nullptr) {
486             continue;
487         }
488         count += layer->GetSurface()->GetName().length();
489         if (max < layer->GetZorder()) {
490             max = layer->GetZorder();
491         }
492     }
493     bool exceedLimit = count > MAX_TOTAL_SURFACE_NAME_LENGTH;
494     std::string surfaceName = "Names:";
495     for (const auto& layer : layers) {
496         if (layer == nullptr || layer->GetSurface() == nullptr) {
497             continue;
498         }
499         surfaceName += (exceedLimit ? layer->GetSurface()->GetName().substr(0, MAX_SINGLE_SURFACE_NAME_LENGTH) :
500                                       layer->GetSurface()->GetName()) + ",";
501         surfaceName.append("zorder: ");
502         surfaceName.append(std::to_string(layer->GetZorder()));
503         surfaceName.append(",");
504         if (layer->GetType() == GraphicLayerType::GRAPHIC_LAYER_TYPE_CURSOR && layer->GetZorder() < max) {
505             RS_LOGE("RSHardcursor is not on the top, hardcursor zorder:%{public}d", layer->GetZorder());
506         }
507     }
508 
509     return surfaceName;
510 }
511 
RecordTimestamp(const std::vector<LayerInfoPtr> & layers)512 void RSHardwareThread::RecordTimestamp(const std::vector<LayerInfoPtr>& layers)
513 {
514     uint64_t currentTime = static_cast<uint64_t>(
515         std::chrono::duration_cast<std::chrono::nanoseconds>(
516         std::chrono::steady_clock::now().time_since_epoch()).count());
517     for (auto& layer : layers) {
518         if (layer == nullptr) {
519             continue;
520         }
521         uint64_t id = layer->GetNodeId();
522         auto& surfaceFpsManager = RSSurfaceFpsManager::GetInstance();
523         if (layer->GetBuffer() == nullptr) {
524             continue;
525         }
526         surfaceFpsManager.RecordPresentTime(id, currentTime, layer->GetBuffer()->GetSeqNum());
527     }
528 }
529 
IsDelayRequired(OHOS::Rosen::HgmCore & hgmCore,RefreshRateParam param,const OutputPtr & output,bool hasGameScene)530 bool RSHardwareThread::IsDelayRequired(OHOS::Rosen::HgmCore& hgmCore, RefreshRateParam param,
531     const OutputPtr& output, bool hasGameScene)
532 {
533     if (param.isForceRefresh) {
534         RS_LOGD("CommitAndReleaseLayers in Force Refresh");
535         RS_TRACE_NAME("CommitAndReleaseLayers in Force Refresh");
536         return false;
537     }
538 
539     if (hgmCore.GetLtpoEnabled()) {
540         if (AdaptiveModeStatus(output) == SupportASStatus::SUPPORT_AS) {
541             RS_LOGD("CommitAndReleaseLayers in Adaptive Mode");
542             RS_TRACE_NAME("CommitAndReleaseLayers in Adaptive Mode");
543             return false;
544         }
545         if (hasGameScene && AdaptiveModeStatus(output) == SupportASStatus::GAME_SCENE_SKIP) {
546             RS_LOGD("CommitAndReleaseLayers skip delayTime Calculation");
547             RS_TRACE_NAME("CommitAndReleaseLayers in Game Scene and skiped delayTime Calculation");
548             return false;
549         }
550     } else {
551         if (!hgmCore.IsDelayMode()) {
552             return false;
553         }
554         if (hasGameScene) {
555             RS_LOGD("CommitAndReleaseLayers in Game Scene");
556             RS_TRACE_NAME("CommitAndReleaseLayers in Game Scene");
557             return false;
558         }
559     }
560     return true;
561 }
562 
CalculateDelayTime(OHOS::Rosen::HgmCore & hgmCore,RefreshRateParam param,uint32_t currentRate,int64_t currTime)563 void RSHardwareThread::CalculateDelayTime(OHOS::Rosen::HgmCore& hgmCore, RefreshRateParam param, uint32_t currentRate,
564     int64_t currTime)
565 {
566     int64_t frameOffset = 0;
567     int64_t vsyncOffset = 0;
568     int64_t idealPipelineOffset = 0;
569     int64_t pipelineOffset = 0;
570     int64_t expectCommitTime = 0;
571     int64_t periodNum = 0;
572     int64_t idealPeriod = hgmCore.GetIdealPeriod(currentRate);
573     int64_t period  = CreateVSyncSampler()->GetHardwarePeriod();
574     uint64_t dvsyncOffset = RSMainThread::Instance()->GetRealTimeOffsetOfDvsync(param.frameTimestamp);
575     int64_t compositionTime = period;
576 
577     if (!hgmCore.GetLtpoEnabled()) {
578         vsyncOffset = UNI_RENDER_VSYNC_OFFSET_DELAY_MODE;
579         // 2 period for draw and composition, pipelineOffset = 2 * period
580         frameOffset = 2 * period + vsyncOffset - static_cast<int64_t>(param.fastComposeTimeStampDiff);
581     } else {
582         idealPipelineOffset = hgmCore.GetIdealPipelineOffset();
583         pipelineOffset = hgmCore.GetPipelineOffset();
584         vsyncOffset = CreateVSyncGenerator()->GetVSyncOffset();
585         periodNum = idealPeriod == 0 ? 0 : idealPipelineOffset / idealPeriod;
586 
587         if (vsyncOffset >= period) {
588             vsyncOffset = 0;
589         }
590         if (periodNum * idealPeriod + vsyncOffset + IDEAL_PULSE < idealPipelineOffset) {
591             periodNum = periodNum + 1;
592         }
593         frameOffset = periodNum * idealPeriod + vsyncOffset +
594             static_cast<int64_t>(dvsyncOffset) - static_cast<int64_t>(param.fastComposeTimeStampDiff);
595     }
596     expectCommitTime = param.actualTimestamp + frameOffset - compositionTime - RESERVE_TIME;
597     int64_t diffTime = expectCommitTime - currTime;
598     if (diffTime > 0 && period > 0) {
599         delayTime_ = std::round(diffTime * 1.0f / NS_MS_UNIT_CONVERSION);
600     }
601     RS_TRACE_NAME_FMT("CalculateDelayTime pipelineOffset: %" PRId64 ", actualTimestamp: %" PRId64 ", " \
602         "expectCommitTime: %" PRId64 ", currTime: %" PRId64 ", diffTime: %" PRId64 ", delayTime: %" PRId64 ", " \
603         "frameOffset: %" PRId64 ", dvsyncOffset: %" PRIu64 ", vsyncOffset: %" PRId64 ", idealPeriod: %" PRId64 ", " \
604         "period: %" PRId64 ", idealPipelineOffset: %" PRId64 ", fastComposeTimeStampDiff: %" PRIu64 "",
605         pipelineOffset, param.actualTimestamp, expectCommitTime, currTime, diffTime, delayTime_,
606         frameOffset, dvsyncOffset, vsyncOffset, idealPeriod, period,
607         idealPipelineOffset, param.fastComposeTimeStampDiff);
608     RS_LOGD_IF(DEBUG_PIPELINE, "CalculateDelayTime period:%{public}" PRId64 " delayTime:%{public}" PRId64 "", period,
609         delayTime_);
610 }
611 
GetCurTimeCount()612 int64_t RSHardwareThread::GetCurTimeCount()
613 {
614     auto curTime = std::chrono::system_clock::now().time_since_epoch();
615     return std::chrono::duration_cast<std::chrono::microseconds>(curTime).count();
616 }
617 
PreAllocateProtectedBuffer(sptr<SurfaceBuffer> buffer,uint64_t screenId)618 void RSHardwareThread::PreAllocateProtectedBuffer(sptr<SurfaceBuffer> buffer, uint64_t screenId)
619 {
620     RS_TRACE_NAME("RSHardwareThread::PreAllocateProtectedBuffer enter.");
621     {
622         std::unique_lock<std::mutex> lock(preAllocMutex_, std::try_to_lock);
623         if (!lock.owns_lock()) {
624             RS_TRACE_NAME("RSHardwareThread::PreAllocateProtectedBuffer failed, HardwareThread is redraw.");
625             return;
626         }
627     }
628     auto screenManager = CreateOrGetScreenManager();
629     auto screenInfo = screenManager->QueryScreenInfo(screenId);
630     auto output = screenManager->GetOutput(ToScreenPhysicalId(screenId));
631     if (output == nullptr) {
632         RS_LOGE("output is NULL");
633         return;
634     }
635     if (output->GetProtectedFrameBufferState()) {
636         return;
637     }
638     auto fbSurface = output->GetFrameBufferSurface();
639     if (fbSurface == nullptr) {
640         RS_LOGE("fbSurface is NULL");
641         return;
642     }
643 #ifdef RS_ENABLE_VK
644     std::lock_guard<std::mutex> ohosSurfaceLock(surfaceMutex_);
645     std::shared_ptr<RSSurfaceOhosVulkan> rsSurface;
646     auto surfaceId = fbSurface->GetUniqueId();
647     {
648         std::lock_guard<std::mutex> lock(frameBufferSurfaceOhosMapMutex_);
649         if (frameBufferSurfaceOhosMap_.count(surfaceId)) {
650             rsSurface = std::static_pointer_cast<RSSurfaceOhosVulkan>(frameBufferSurfaceOhosMap_[surfaceId]);
651         } else {
652             rsSurface = std::make_shared<RSSurfaceOhosVulkan>(fbSurface);
653             frameBufferSurfaceOhosMap_[surfaceId] = rsSurface;
654         }
655     }
656     // SetColorSpace
657     rsSurface->SetColorSpace(ComputeTargetColorGamut(buffer));
658 
659     // SetSurfacePixelFormat
660     rsSurface->SetSurfacePixelFormat(ComputeTargetPixelFormat(buffer));
661 
662     // SetSurfaceBufferUsage
663     auto usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_MEM_DMA | BUFFER_USAGE_MEM_FB | BUFFER_USAGE_PROTECTED |
664         BUFFER_USAGE_DRM_REDRAW;
665     rsSurface->SetSurfaceBufferUsage(usage);
666     auto ret = rsSurface->PreAllocateProtectedBuffer(screenInfo.phyWidth, screenInfo.phyHeight);
667     output->SetProtectedFrameBufferState(ret);
668 #endif
669 }
670 
ComputeTargetColorGamut(const sptr<SurfaceBuffer> & buffer)671 GraphicColorGamut RSHardwareThread::ComputeTargetColorGamut(const sptr<SurfaceBuffer> &buffer)
672 {
673     GraphicColorGamut colorGamut = GRAPHIC_COLOR_GAMUT_SRGB;
674 #ifdef USE_VIDEO_PROCESSING_ENGINE
675     using namespace HDI::Display::Graphic::Common::V1_0;
676     CM_ColorSpaceInfo colorSpaceInfo;
677     if (MetadataHelper::GetColorSpaceInfo(buffer, colorSpaceInfo) != GSERROR_OK) {
678         RS_LOGD("PreAllocateProtectedBuffer Get color space failed");
679     }
680     if (colorSpaceInfo.primaries != COLORPRIMARIES_SRGB) {
681         RS_LOGD("PreAllocateProtectedBuffer fail, primaries is %{public}d", colorSpaceInfo.primaries);
682         colorGamut = GRAPHIC_COLOR_GAMUT_DISPLAY_P3;
683     }
684 #endif
685     return colorGamut;
686 }
687 
ComputeTargetPixelFormat(const sptr<SurfaceBuffer> & buffer)688 GraphicPixelFormat RSHardwareThread::ComputeTargetPixelFormat(const sptr<SurfaceBuffer> &buffer)
689 {
690     GraphicPixelFormat pixelFormat = GRAPHIC_PIXEL_FMT_RGBA_8888;
691 #ifdef USE_VIDEO_PROCESSING_ENGINE
692     using namespace HDI::Display::Graphic::Common::V1_0;
693     auto bufferPixelFormat = buffer->GetFormat();
694     if (bufferPixelFormat == GRAPHIC_PIXEL_FMT_RGBA_1010102 || bufferPixelFormat == GRAPHIC_PIXEL_FMT_YCBCR_P010 ||
695         bufferPixelFormat == GRAPHIC_PIXEL_FMT_YCRCB_P010) {
696         pixelFormat = GRAPHIC_PIXEL_FMT_RGBA_1010102;
697         RS_LOGD("PreAllocateProtectedBuffer pixelformat is set to 1010102 for 10bit buffer");
698     }
699 #endif
700     return pixelFormat;
701 }
702 
AdaptiveModeStatus(const OutputPtr & output)703 int32_t RSHardwareThread::AdaptiveModeStatus(const OutputPtr &output)
704 {
705     if (hdiBackend_ == nullptr) {
706         RS_LOGE("AdaptiveModeStatus hdiBackend_ is nullptr");
707         return SupportASStatus::NOT_SUPPORT;
708     }
709 
710     auto& hgmCore = OHOS::Rosen::HgmCore::Instance();
711 
712     // if in game adaptive vsync mode and do direct composition,send layer immediately
713     auto frameRateMgr = hgmCore.GetFrameRateMgr();
714     if (frameRateMgr != nullptr) {
715         int32_t adaptiveStatus = frameRateMgr->AdaptiveStatus();
716         RS_LOGD("CommitAndReleaseLayers send layer adaptiveStatus: %{public}u", adaptiveStatus);
717         if (adaptiveStatus == SupportASStatus::SUPPORT_AS) {
718             return SupportASStatus::SUPPORT_AS;
719         }
720         if (adaptiveStatus == SupportASStatus::GAME_SCENE_SKIP) {
721             return SupportASStatus::GAME_SCENE_SKIP;
722         }
723     }
724     return SupportASStatus::NOT_SUPPORT;
725 }
726 
OnScreenVBlankIdleCallback(ScreenId screenId,uint64_t timestamp)727 void RSHardwareThread::OnScreenVBlankIdleCallback(ScreenId screenId, uint64_t timestamp)
728 {
729     RS_TRACE_NAME_FMT("RSHardwareThread::OnScreenVBlankIdleCallback screenId: %" PRIu64" now: %" PRIu64"",
730         screenId, timestamp);
731     hgmHardwareUtils_.SetScreenVBlankIdle(screenId);
732 }
733 
IsDropDirtyFrame(const std::vector<LayerInfoPtr> & layerInfos,uint32_t screenId)734 bool RSHardwareThread::IsDropDirtyFrame(const std::vector<LayerInfoPtr>& layerInfos, uint32_t screenId)
735 {
736 #ifdef ROSEN_EMULATOR
737     RS_LOGD("emulator device do not need drop dirty frame");
738     return false;
739 #endif
740     if (!RSSystemProperties::IsSuperFoldDisplay()) {
741         return false;
742     }
743     auto screenManager = CreateOrGetScreenManager();
744     if (screenManager == nullptr) {
745         RS_LOGW("%{public}s: screenManager is null", __func__);
746         return false;
747     }
748 
749     auto rect = screenManager->QueryScreenInfo(screenId).activeRect;
750     if (rect.IsEmpty()) {
751         RS_LOGW("%{public}s: activeRect is empty", __func__);
752         return false;
753     }
754     GraphicIRect activeRect = {rect.left_, rect.top_, rect.width_, rect.height_};
755     if (layerInfos.empty()) {
756         RS_LOGI("%{public}s: layerInfos is empty", __func__);
757         return false;
758     }
759     for (const auto& info : layerInfos) {
760         if (info == nullptr) {
761             continue;
762         }
763         auto layerSize = info->GetLayerSize();
764         if (info->GetUniRenderFlag() && !(activeRect == layerSize)) {
765             RS_LOGI("%{publkic}s: Drop dirty frame cause activeRect:[%{public}d, %{public}d, %{public}d, %{public}d]" \
766                 "layerSize:[%{public}d, %{public}d, %{public}d, %{public}d]", __func__, activeRect.x, activeRect.y,
767                 activeRect.w, activeRect.h, layerSize.x, layerSize.y, layerSize.w, layerSize.h);
768             return true;
769         }
770     }
771     return false;
772 }
773 
OnPrepareComplete(sptr<Surface> & surface,const PrepareCompleteParam & param,void * data)774 void RSHardwareThread::OnPrepareComplete(sptr<Surface>& surface,
775     const PrepareCompleteParam& param, void* data)
776 {
777     // unused data.
778     (void)(data);
779 
780     if (!param.needFlushFramebuffer) {
781         return;
782     }
783 
784     if (redrawCb_ != nullptr) {
785         redrawCb_(surface, param.layers, param.screenId);
786     }
787 }
788 
ClearFrameBuffers(OutputPtr output)789 GSError RSHardwareThread::ClearFrameBuffers(OutputPtr output)
790 {
791     if (output == nullptr) {
792         RS_LOGE("Clear frame buffers failed for the output is nullptr");
793         return GSERROR_INVALID_ARGUMENTS;
794     }
795     RS_TRACE_NAME("RSHardwareThread::ClearFrameBuffers");
796     if (uniRenderEngine_ != nullptr) {
797         uniRenderEngine_->ResetCurrentContext();
798     }
799     auto surface = output->GetFrameBufferSurface();
800     auto surfaceId = surface->GetUniqueId();
801     std::lock_guard<std::mutex> ohosSurfaceLock(surfaceMutex_);
802     std::shared_ptr<RSSurfaceOhos> frameBufferSurfaceOhos;
803     {
804         std::lock_guard<std::mutex> lock(frameBufferSurfaceOhosMapMutex_);
805         if (frameBufferSurfaceOhosMap_.count(surfaceId)) {
806             frameBufferSurfaceOhos = frameBufferSurfaceOhosMap_[surfaceId];
807         }
808         if (frameBufferSurfaceOhos != nullptr) {
809 #ifdef RS_ENABLE_VK
810             if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
811                 RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
812                 auto frameBufferSurface = std::static_pointer_cast<RSSurfaceOhosVulkan>(frameBufferSurfaceOhos);
813                 if (frameBufferSurface) {
814                     frameBufferSurface->WaitSurfaceClear();
815                 }
816             }
817 #endif
818             frameBufferSurfaceOhosMap_.erase(surfaceId);
819         }
820     }
821     return output->ClearFrameBuffer();
822 }
823 
CreateFrameBufferSurfaceOhos(const sptr<Surface> & surface)824 std::shared_ptr<RSSurfaceOhos> RSHardwareThread::CreateFrameBufferSurfaceOhos(const sptr<Surface>& surface)
825 {
826     std::shared_ptr<RSSurfaceOhos> rsSurface = nullptr;
827 #if (defined RS_ENABLE_GL) && (defined RS_ENABLE_EGLIMAGE)
828     if (RSSystemProperties::GetGpuApiType() == GpuApiType::OPENGL) {
829         rsSurface = std::make_shared<RSSurfaceOhosGl>(surface);
830     }
831 #endif
832 #if (defined RS_ENABLE_VK)
833     if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
834         RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
835         rsSurface = std::make_shared<RSSurfaceOhosVulkan>(surface);
836     }
837 #endif
838     RS_LOGD("Redraw: CreateFrameBufferSurfaceOhos.");
839     return rsSurface;
840 }
841 
RedrawScreenRCD(RSPaintFilterCanvas & canvas,const std::vector<LayerInfoPtr> & layers)842 void RSHardwareThread::RedrawScreenRCD(RSPaintFilterCanvas& canvas, const std::vector<LayerInfoPtr>& layers)
843 {
844     RS_TRACE_NAME("RSHardwareThread::RedrawScreenRCD");
845     using RSRcdManager = RSSingleton<RoundCornerDisplayManager>;
846     std::vector<std::pair<NodeId, RoundCornerDisplayManager::RCDLayerType>> rcdLayerInfoList;
847     for (const auto& layer : layers) {
848         if (layer == nullptr) {
849             continue;
850         }
851         if (layer->GetCompositionType() == GraphicCompositionType::GRAPHIC_COMPOSITION_DEVICE ||
852             layer->GetCompositionType() == GraphicCompositionType::GRAPHIC_COMPOSITION_DEVICE_CLEAR ||
853             layer->GetCompositionType() == GraphicCompositionType::GRAPHIC_COMPOSITION_SOLID_COLOR) {
854             continue;
855         }
856         auto layerSurface = layer->GetSurface();
857         if (layerSurface != nullptr) {
858             auto rcdlayerInfo = RSRcdManager::GetInstance().GetLayerPair(layerSurface->GetName());
859             if (rcdlayerInfo.second != RoundCornerDisplayManager::RCDLayerType::INVALID) {
860                 rcdLayerInfoList.push_back(rcdlayerInfo);
861                 continue;
862             }
863         } else {
864             RS_LOGE("RedrawScreenRCD layerSurface is nullptr");
865             continue;
866         }
867     }
868 
869     if (RSRcdManager::GetInstance().GetRcdEnable()) {
870         RSRcdManager::GetInstance().DrawRoundCorner(rcdLayerInfoList, &canvas);
871     }
872 }
873 
Redraw(const sptr<Surface> & surface,const std::vector<LayerInfoPtr> & layers,uint32_t screenId)874 void RSHardwareThread::Redraw(const sptr<Surface>& surface, const std::vector<LayerInfoPtr>& layers, uint32_t screenId)
875 {
876     RS_TRACE_NAME("RSHardwareThread::Redraw");
877     std::unique_lock<std::mutex> lock(preAllocMutex_, std::try_to_lock);
878     auto screenManager = CreateOrGetScreenManager();
879     if (screenManager == nullptr) {
880         RS_LOGE("Redraw: screenManager is null.");
881         return;
882     }
883     if (surface == nullptr || uniRenderEngine_ == nullptr) {
884         RS_LOGE("Redraw: surface or uniRenderEngine is null.");
885         return;
886     }
887     bool isProtected = false;
888 
889     static bool isCCMDrmEnabled = DRMParam::IsDrmEnable();
890     bool isDrmEnabled = RSSystemProperties::GetDrmEnabled() && isCCMDrmEnabled;
891 
892 #ifdef RS_ENABLE_VK
893     if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
894         RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
895         if (isDrmEnabled) {
896             for (const auto& layer : layers) {
897                 if (layer && layer->GetBuffer() && (layer->GetBuffer()->GetUsage() & BUFFER_USAGE_PROTECTED)) {
898                     isProtected = true;
899                     break;
900                 }
901             }
902             if (RSSystemProperties::IsUseVulkan()) {
903                 RsVulkanContext::GetSingleton().SetIsProtected(isProtected);
904             }
905         } else {
906             RsVulkanContext::GetSingleton().SetIsProtected(false);
907         }
908     }
909 #endif
910 
911     RS_LOGD("RsDebug Redraw flush frame buffer start");
912     bool forceCPU = RSBaseRenderEngine::NeedForceCPU(layers);
913     auto screenInfo = screenManager->QueryScreenInfo(screenId);
914     std::shared_ptr<Drawing::ColorSpace> drawingColorSpace = nullptr;
915 #ifdef USE_VIDEO_PROCESSING_ENGINE
916     GraphicColorGamut colorGamut = ComputeTargetColorGamut(layers);
917     GraphicPixelFormat pixelFormat = ComputeTargetPixelFormat(layers);
918     RS_LOGD("Redraw computed target color gamut: %{public}d,"
919         "pixel format: %{public}d, frame width: %{public}d, frame height: %{public}d",
920         colorGamut, pixelFormat, screenInfo.phyWidth, screenInfo.phyHeight);
921     auto renderFrameConfig = RSBaseRenderUtil::GetFrameBufferRequestConfig(screenInfo,
922         isProtected, colorGamut, pixelFormat);
923     drawingColorSpace = RSBaseRenderEngine::ConvertColorGamutToDrawingColorSpace(colorGamut);
924     // set color space to surface buffer metadata
925     using namespace HDI::Display::Graphic::Common::V1_0;
926     CM_ColorSpaceType colorSpace = CM_SRGB_FULL;
927     if (ConvertColorGamutToSpaceType(colorGamut, colorSpace)) {
928         if (surface->SetUserData("ATTRKEY_COLORSPACE_INFO", std::to_string(colorSpace)) != GSERROR_OK) {
929             RS_LOGD("Redraw set user data failed");
930         }
931     }
932 #else
933     auto renderFrameConfig = RSBaseRenderUtil::GetFrameBufferRequestConfig(screenInfo, isProtected);
934 #endif
935     // override redraw frame buffer with physical screen resolution.
936     renderFrameConfig.width = static_cast<int32_t>(screenInfo.phyWidth);
937     renderFrameConfig.height = static_cast<int32_t>(screenInfo.phyHeight);
938 
939     std::shared_ptr<RSSurfaceOhos> frameBufferSurfaceOhos;
940     auto surfaceId = surface->GetUniqueId();
941     {
942         std::lock_guard<std::mutex> lock(frameBufferSurfaceOhosMapMutex_);
943         if (frameBufferSurfaceOhosMap_.count(surfaceId)) {
944             frameBufferSurfaceOhos = frameBufferSurfaceOhosMap_[surfaceId];
945         } else {
946             frameBufferSurfaceOhos = CreateFrameBufferSurfaceOhos(surface);
947             frameBufferSurfaceOhosMap_[surfaceId] = frameBufferSurfaceOhos;
948         }
949     }
950     FrameContextConfig frameContextConfig = FrameContextConfig(isProtected);
951     std::lock_guard<std::mutex> ohosSurfaceLock(surfaceMutex_);
952     auto renderFrame = uniRenderEngine_->RequestFrame(frameBufferSurfaceOhos, renderFrameConfig,
953         forceCPU, true, frameContextConfig);
954     if (renderFrame == nullptr) {
955         RS_LOGE("RsDebug Redraw failed to request frame.");
956         return;
957     }
958     auto canvas = renderFrame->GetCanvas();
959     if (canvas == nullptr) {
960         RS_LOGE("RsDebug Redraw canvas is nullptr.");
961         return;
962     }
963 #ifdef RS_ENABLE_VK
964     if (RSSystemProperties::IsUseVulkan()) {
965         canvas->Clear(Drawing::Color::COLOR_TRANSPARENT);
966     }
967 #endif
968 
969 #ifdef USE_VIDEO_PROCESSING_ENGINE
970     uniRenderEngine_->DrawLayers(*canvas, layers, false, screenInfo, colorGamut);
971 #else
972     uniRenderEngine_->DrawLayers(*canvas, layers, false, screenInfo);
973 #endif
974     RedrawScreenRCD(*canvas, layers);
975 #ifdef RS_ENABLE_TV_PQ_METADATA
976     auto rsSurface = renderFrame->GetSurface();
977     RSTvMetadataManager::Instance().CopyFromLayersToSurface(layers, rsSurface);
978 #endif
979     renderFrame->Flush();
980     RS_LOGD("RsDebug Redraw flush frame buffer end");
981 }
982 
AddRefreshRateCount(const OutputPtr & output)983 void RSHardwareThread::AddRefreshRateCount(const OutputPtr& output)
984 {
985     auto screenManager = CreateOrGetScreenManager();
986     if (screenManager == nullptr) {
987         RS_LOGE("AddRefreshRateCount screenManager is nullptr");
988         return;
989     }
990     ScreenId id = screenManager->GetDefaultScreenId();
991     auto& hgmCore = OHOS::Rosen::HgmCore::Instance();
992     uint32_t currentRefreshRate = hgmCore.GetScreenCurrentRefreshRate(id);
993     auto [iter, success] = refreshRateCounts_.try_emplace(currentRefreshRate, 1);
994     if (!success) {
995         iter->second++;
996     }
997     if (output == nullptr) {
998         return;
999     }
1000     RSRealtimeRefreshRateManager::Instance().CountRealtimeFrame(output->GetScreenId());
1001     auto frameRateMgr = HgmCore::Instance().GetFrameRateMgr();
1002     if (frameRateMgr == nullptr) {
1003         RS_LOGE("AddRefreshData fail, frameBufferSurfaceOhos_ is nullptr");
1004         return;
1005     }
1006     frameRateMgr->HandleRsFrame();
1007 }
1008 
SubScribeSystemAbility()1009 void RSHardwareThread::SubScribeSystemAbility()
1010 {
1011     RS_LOGI("%{public}s", __func__);
1012     sptr<ISystemAbilityManager> systemAbilityManager =
1013         SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
1014     if (!systemAbilityManager) {
1015         RS_LOGE("%{public}s failed to get system ability manager client", __func__);
1016         return;
1017     }
1018     std::string threadName = "RSHardwareThread";
1019     std::string strUid = std::to_string(getuid());
1020     std::string strPid = std::to_string(getpid());
1021     std::string strTid = std::to_string(gettid());
1022 
1023     saStatusChangeListener_ = new (std::nothrow)VSyncSystemAbilityListener(threadName, strUid, strPid, strTid);
1024     int32_t ret = systemAbilityManager->SubscribeSystemAbility(RES_SCHED_SYS_ABILITY_ID, saStatusChangeListener_);
1025     if (ret != ERR_OK) {
1026         RS_LOGE("%{public}s subscribe system ability %{public}d failed.", __func__, RES_SCHED_SYS_ABILITY_ID);
1027         saStatusChangeListener_ = nullptr;
1028     }
1029 }
1030 
DumpEventQueue()1031 void RSHardwareThread::DumpEventQueue()
1032 {
1033     if (handler_ != nullptr) {
1034         AppExecFwk::RSHardwareDumper dumper;
1035         handler_->Dump(dumper);
1036         dumper.PrintDumpInfo();
1037     }
1038 }
1039 
1040 #ifdef USE_VIDEO_PROCESSING_ENGINE
ComputeTargetColorGamut(const std::vector<LayerInfoPtr> & layers)1041 GraphicColorGamut RSHardwareThread::ComputeTargetColorGamut(const std::vector<LayerInfoPtr>& layers)
1042 {
1043     using namespace HDI::Display::Graphic::Common::V1_0;
1044     GraphicColorGamut colorGamut = GRAPHIC_COLOR_GAMUT_SRGB;
1045     for (auto& layer : layers) {
1046         if (layer == nullptr) {
1047             RS_LOGE("ComputeTargetColorGamut layer is nullptr");
1048             continue;
1049         }
1050         auto buffer = layer->GetBuffer();
1051         if (buffer == nullptr) {
1052             RS_LOGW("ComputeTargetColorGamut The buffer of layer is nullptr");
1053             continue;
1054         }
1055 
1056         CM_ColorSpaceInfo colorSpaceInfo;
1057         if (MetadataHelper::GetColorSpaceInfo(buffer, colorSpaceInfo) != GSERROR_OK) {
1058             RS_LOGD("ComputeTargetColorGamut Get color space failed");
1059             continue;
1060         }
1061 
1062         if (colorSpaceInfo.primaries != COLORPRIMARIES_SRGB) {
1063             RS_LOGD("ComputeTargetColorData fail, primaries is %{public}d",
1064                 colorSpaceInfo.primaries);
1065             colorGamut = GRAPHIC_COLOR_GAMUT_DISPLAY_P3;
1066             break;
1067         }
1068     }
1069 
1070     return colorGamut;
1071 }
1072 
IsAllRedraw(const std::vector<LayerInfoPtr> & layers)1073 bool RSHardwareThread::IsAllRedraw(const std::vector<LayerInfoPtr>& layers)
1074 {
1075     using RSRcdManager = RSSingleton<RoundCornerDisplayManager>;
1076     for (auto& layer : layers) {
1077         if (layer == nullptr) {
1078             continue;
1079         }
1080         // skip RCD layer
1081         auto layerSurface = layer->GetSurface();
1082         if (layerSurface != nullptr) {
1083             auto rcdlayerInfo = RSRcdManager::GetInstance().GetLayerPair(layerSurface->GetName());
1084             if (rcdlayerInfo.second != RoundCornerDisplayManager::RCDLayerType::INVALID) {
1085                 RS_LOGD("IsAllRedraw skip RCD layer");
1086                 continue;
1087             }
1088         }
1089         // skip hard cursor
1090         if (layer->GetType() == GraphicLayerType::GRAPHIC_LAYER_TYPE_CURSOR) {
1091             RS_LOGD("IsAllRedraw skip cursor");
1092             continue;
1093         }
1094         if (layer->GetCompositionType() == GraphicCompositionType::GRAPHIC_COMPOSITION_DEVICE ||
1095             layer->GetCompositionType() == GraphicCompositionType::GRAPHIC_COMPOSITION_DEVICE_CLEAR ||
1096             layer->GetCompositionType() == GraphicCompositionType::GRAPHIC_COMPOSITION_SOLID_COLOR) {
1097             RS_LOGD("IsAllRedraw not all layers are redraw");
1098             return false;
1099         }
1100     }
1101     return true;
1102 }
1103 
ComputeTargetPixelFormat(const std::vector<LayerInfoPtr> & layers)1104 GraphicPixelFormat RSHardwareThread::ComputeTargetPixelFormat(const std::vector<LayerInfoPtr>& layers)
1105 {
1106     using namespace HDI::Display::Graphic::Common::V1_0;
1107     GraphicPixelFormat pixelFormat = GRAPHIC_PIXEL_FMT_RGBA_8888;
1108     bool allRedraw = IsAllRedraw(layers);
1109     for (auto& layer : layers) {
1110         if (layer == nullptr) {
1111             continue;
1112         }
1113         if (layer->GetCompositionType() == GraphicCompositionType::GRAPHIC_COMPOSITION_DEVICE ||
1114             layer->GetCompositionType() == GraphicCompositionType::GRAPHIC_COMPOSITION_DEVICE_CLEAR ||
1115             layer->GetCompositionType() == GraphicCompositionType::GRAPHIC_COMPOSITION_SOLID_COLOR) {
1116             continue;
1117         }
1118         auto buffer = layer->GetBuffer();
1119         if (buffer == nullptr) {
1120             RS_LOGW("ComputeTargetPixelFormat The buffer of layer is nullptr");
1121             continue;
1122         }
1123 
1124         auto bufferPixelFormat = buffer->GetFormat();
1125         if (bufferPixelFormat == GRAPHIC_PIXEL_FMT_RGBA_1010108) {
1126             pixelFormat = GRAPHIC_PIXEL_FMT_RGBA_1010102;
1127             if (!allRedraw && RSHdrUtil::GetRGBA1010108Enabled()) {
1128                 pixelFormat = GRAPHIC_PIXEL_FMT_RGBA_1010108;
1129                 RS_LOGD("ComputeTargetPixelFormat pixelformat is set to GRAPHIC_PIXEL_FMT_RGBA_1010108");
1130             }
1131             break;
1132         }
1133         if (bufferPixelFormat == GRAPHIC_PIXEL_FMT_RGBA_1010102 ||
1134             bufferPixelFormat == GRAPHIC_PIXEL_FMT_YCBCR_P010 ||
1135             bufferPixelFormat == GRAPHIC_PIXEL_FMT_YCRCB_P010) {
1136             pixelFormat = GRAPHIC_PIXEL_FMT_RGBA_1010102;
1137             RS_LOGD("ComputeTargetPixelFormat pixelformat is set to 1010102 for 10bit buffer");
1138         }
1139     }
1140 
1141     return pixelFormat;
1142 }
1143 
ConvertColorGamutToSpaceType(const GraphicColorGamut & colorGamut,HDI::Display::Graphic::Common::V1_0::CM_ColorSpaceType & colorSpaceType)1144 bool RSHardwareThread::ConvertColorGamutToSpaceType(const GraphicColorGamut& colorGamut,
1145     HDI::Display::Graphic::Common::V1_0::CM_ColorSpaceType& colorSpaceType)
1146 {
1147     using namespace HDI::Display::Graphic::Common::V1_0;
1148     static const std::map<GraphicColorGamut, CM_ColorSpaceType> RS_TO_COMMON_COLOR_SPACE_TYPE_MAP {
1149         {GRAPHIC_COLOR_GAMUT_STANDARD_BT601, CM_BT601_EBU_FULL},
1150         {GRAPHIC_COLOR_GAMUT_STANDARD_BT709, CM_BT709_FULL},
1151         {GRAPHIC_COLOR_GAMUT_SRGB, CM_SRGB_FULL},
1152         {GRAPHIC_COLOR_GAMUT_ADOBE_RGB, CM_ADOBERGB_FULL},
1153         {GRAPHIC_COLOR_GAMUT_DISPLAY_P3, CM_P3_FULL},
1154         {GRAPHIC_COLOR_GAMUT_BT2020, CM_DISPLAY_BT2020_SRGB},
1155         {GRAPHIC_COLOR_GAMUT_BT2100_PQ, CM_BT2020_PQ_FULL},
1156         {GRAPHIC_COLOR_GAMUT_BT2100_HLG, CM_BT2020_HLG_FULL},
1157         {GRAPHIC_COLOR_GAMUT_DISPLAY_BT2020, CM_DISPLAY_BT2020_SRGB},
1158     };
1159 
1160     if (RS_TO_COMMON_COLOR_SPACE_TYPE_MAP.find(colorGamut) == RS_TO_COMMON_COLOR_SPACE_TYPE_MAP.end()) {
1161         return false;
1162     }
1163 
1164     colorSpaceType = RS_TO_COMMON_COLOR_SPACE_TYPE_MAP.at(colorGamut);
1165     return true;
1166 }
1167 #endif
1168 
ContextRegisterPostTask()1169 void RSHardwareThread::ContextRegisterPostTask()
1170 {
1171 #if defined(RS_ENABLE_VK) && defined(IS_ENABLE_DRM)
1172     if (RSSystemProperties::IsUseVulkan()) {
1173         RsVulkanContext::GetSingleton().SetIsProtected(true);
1174         auto context = RsVulkanContext::GetSingleton().GetDrawingContext();
1175         if (context) {
1176             context->RegisterPostFunc([this](const std::function<void()>& task) { PostTask(task); });
1177         }
1178         RsVulkanContext::GetSingleton().SetIsProtected(false);
1179         if (context) {
1180             context->RegisterPostFunc([this](const std::function<void()>& task) { PostTask(task); });
1181         }
1182     }
1183 #endif
1184 }
1185 }
1186 
1187 namespace OHOS {
1188 namespace AppExecFwk {
Dump(const std::string & message)1189 void RSHardwareDumper::Dump(const std::string& message)
1190 {
1191     dumpInfo_ += message;
1192 }
1193 
GetTag()1194 std::string RSHardwareDumper::GetTag()
1195 {
1196     return "RSHardwareDumper";
1197 }
1198 
PrintDumpInfo()1199 void RSHardwareDumper::PrintDumpInfo()
1200 {
1201     if (dumpInfo_.empty()) {
1202         return;
1203     }
1204     size_t compareStrSize = sizeof("}\n");
1205 
1206     size_t curRunningStart = dumpInfo_.find("Current Running: start");
1207     if (curRunningStart != std::string::npos) {
1208         size_t curRunningEnd = dumpInfo_.find("}\n", curRunningStart);
1209         if (curRunningEnd != std::string::npos) {
1210             RS_LOGE("%{public}s",
1211                 dumpInfo_.substr(curRunningStart, curRunningEnd - curRunningStart + compareStrSize).c_str());
1212         }
1213     }
1214 
1215     size_t immediateStart = dumpInfo_.find("Immediate priority event queue information:");
1216     if (immediateStart != std::string::npos) {
1217         size_t immediateEnd = dumpInfo_.find("}\n", immediateStart);
1218         if (immediateEnd != std::string::npos) {
1219             RS_LOGE("%{public}s",
1220                 dumpInfo_.substr(immediateStart, immediateEnd - immediateStart + compareStrSize).c_str());
1221         }
1222     }
1223 }
1224 
1225 } // namespace AppExecFwk
1226 } // namespace OHOS