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