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