1 /*
2 * Copyright (c) 2022-2023 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 "pipeline/rs_hardware_thread.h"
17
18 #include <memory>
19 #include <unistd.h>
20
21 #include "frame_report.h"
22 #include "hdi_backend.h"
23
24 #include "hgm_frame_rate_manager.h"
25 #include "parameters.h"
26 #include "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 "pipeline/round_corner_display/rs_round_corner_display_manager.h"
33 #include "pipeline/rs_base_render_util.h"
34 #include "pipeline/rs_main_thread.h"
35 #include "pipeline/rs_uni_render_engine.h"
36 #include "pipeline/rs_uni_render_thread.h"
37 #include "pipeline/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
44 #ifdef RS_ENABLE_EGLIMAGE
45 #include "src/gpu/gl/GrGLDefines.h"
46 #endif
47
48 #ifdef RS_ENABLE_VK
49 #include "platform/ohos/backend/rs_surface_ohos_vulkan.h"
50 #include "rs_vk_image_manager.h"
51 #endif
52
53 #ifdef RS_ENABLE_EGLIMAGE
54 #include "rs_egl_image_manager.h"
55 #endif // RS_ENABLE_EGLIMAGE
56
57 #ifdef USE_VIDEO_PROCESSING_ENGINE
58 #include "metadata_helper.h"
59 #endif
60
61 #ifdef RES_SCHED_ENABLE
62 #include "system_ability_definition.h"
63 #include "if_system_ability_manager.h"
64 #include <iservice_registry.h>
65 #include "ressched_event_listener.h"
66 #endif
67
68 namespace OHOS::Rosen {
69 namespace {
70 constexpr uint32_t HARDWARE_THREAD_TASK_NUM = 2;
71 constexpr int64_t RESERVE_TIME = 1000000; // we reserve 1ms more for the composition
72 constexpr int64_t COMMIT_DELTA_TIME = 2; // 2ms
73 constexpr int64_t MAX_DELAY_TIME = 100; // 100ms
74 constexpr int64_t NS_MS_UNIT_CONVERSION = 1000000;
75 constexpr int64_t UNI_RENDER_VSYNC_OFFSET_DELAY_MODE = 3300000; // 3.3ms
76 constexpr int64_t PERIOD_60_HZ = 16666666;
77 }
78
SystemTime()79 static int64_t SystemTime()
80 {
81 timespec t = {};
82 clock_gettime(CLOCK_MONOTONIC, &t);
83 return int64_t(t.tv_sec) * 1000000000LL + t.tv_nsec; // 1000000000ns == 1s
84 }
85
Instance()86 RSHardwareThread& RSHardwareThread::Instance()
87 {
88 static RSHardwareThread instance;
89 return instance;
90 }
91
Start()92 void RSHardwareThread::Start()
93 {
94 RS_LOGI("RSHardwareThread::Start()!");
95 hdiBackend_ = HdiBackend::GetInstance();
96 runner_ = AppExecFwk::EventRunner::Create("RSHardwareThread");
97 handler_ = std::make_shared<AppExecFwk::EventHandler>(runner_);
98 redrawCb_ = [this](const sptr<Surface>& surface, const std::vector<LayerInfoPtr>& layers, uint32_t screenId) {
99 return this->Redraw(surface, layers, screenId);
100 };
101 if (handler_) {
102 ScheduleTask(
103 [this]() {
104 auto screenManager = CreateOrGetScreenManager();
105 if (screenManager == nullptr || !screenManager->Init()) {
106 RS_LOGE("RSHardwareThread CreateOrGetScreenManager or init fail.");
107 return;
108 }
109 #ifdef RES_SCHED_ENABLE
110 SubScribeSystemAbility();
111 #endif
112 uniRenderEngine_ = std::make_shared<RSUniRenderEngine>();
113 #ifdef RS_ENABLE_VK
114 if (RSSystemProperties::IsUseVulkan()) {
115 RsVulkanContext::GetSingleton().SetIsProtected(true);
116 }
117 #endif
118 uniRenderEngine_->Init(true);
119 hardwareTid_ = gettid();
120 }).wait();
121 }
122 auto onPrepareCompleteFunc = [this](auto& surface, const auto& param, void* data) {
123 OnPrepareComplete(surface, param, data);
124 };
125 if (hdiBackend_ != nullptr) {
126 hdiBackend_->RegPrepareComplete(onPrepareCompleteFunc, this);
127 }
128 }
129
GetHardwareTid() const130 int RSHardwareThread::GetHardwareTid() const
131 {
132 return hardwareTid_;
133 }
134
PostTask(const std::function<void ()> & task)135 void RSHardwareThread::PostTask(const std::function<void()>& task)
136 {
137 if (handler_) {
138 handler_->PostTask(task, AppExecFwk::EventQueue::Priority::IMMEDIATE);
139 }
140 }
141
PostDelayTask(const std::function<void ()> & task,int64_t delayTime)142 void RSHardwareThread::PostDelayTask(const std::function<void()>& task, int64_t delayTime)
143 {
144 if (handler_) {
145 handler_->PostTask(task, delayTime, AppExecFwk::EventQueue::Priority::IMMEDIATE);
146 }
147 }
148
GetunExecuteTaskNum()149 uint32_t RSHardwareThread::GetunExecuteTaskNum()
150 {
151 return unExecuteTaskNum_.load();
152 }
153
RefreshRateCounts(std::string & dumpString)154 void RSHardwareThread::RefreshRateCounts(std::string& dumpString)
155 {
156 if (refreshRateCounts_.empty()) {
157 return;
158 }
159 std::map<uint32_t, uint64_t>::iterator iter;
160 for (iter = refreshRateCounts_.begin(); iter != refreshRateCounts_.end(); ++iter) {
161 dumpString.append(
162 "Refresh Rate:" + std::to_string(iter->first) + ", Count:" + std::to_string(iter->second) + ";\n");
163 }
164 RS_LOGD("RSHardwareThread::RefreshRateCounts refresh rate counts info is displayed");
165 }
166
ClearRefreshRateCounts(std::string & dumpString)167 void RSHardwareThread::ClearRefreshRateCounts(std::string& dumpString)
168 {
169 if (refreshRateCounts_.empty()) {
170 return;
171 }
172 refreshRateCounts_.clear();
173 dumpString.append("The refresh rate counts info is cleared successfully!\n");
174 RS_LOGD("RSHardwareThread::RefreshRateCounts refresh rate counts info is cleared");
175 }
176
CommitAndReleaseLayers(OutputPtr output,const std::vector<LayerInfoPtr> & layers)177 void RSHardwareThread::CommitAndReleaseLayers(OutputPtr output, const std::vector<LayerInfoPtr>& layers)
178 {
179 if (!handler_) {
180 RS_LOGE("RSHardwareThread::CommitAndReleaseLayers handler is nullptr");
181 return;
182 }
183 delayTime_ = 0;
184 LayerComposeCollection::GetInstance().UpdateUniformOrOfflineComposeFrameNumberForDFX(layers.size());
185 RefreshRateParam param = GetRefreshRateParam();
186 auto& hgmCore = OHOS::Rosen::HgmCore::Instance();
187 uint32_t currentRate = hgmCore.GetScreenCurrentRefreshRate(hgmCore.GetActiveScreenId());
188 bool hasGameScene = FrameReport::GetInstance().HasGameScene();
189 #ifdef RES_SCHED_ENABLE
190 ResschedEventListener::GetInstance()->ReportFrameToRSS();
191 #endif
192 RSTaskMessage::RSTask task = [this, output = output, layers = layers, param = param,
193 currentRate = currentRate, hasGameScene = hasGameScene]() {
194 if (output == nullptr || hdiBackend_ == nullptr) {
195 return;
196 }
197 int64_t startTimeNs = 0;
198 int64_t endTimeNs = 0;
199 RS_LOGI_IF(DEBUG_COMPOSER, "RSHardwareThread::CommitAndReleaseData hasGameScene is %{public}d", hasGameScene);
200 if (hasGameScene) {
201 startTimeNs = std::chrono::duration_cast<std::chrono::nanoseconds>(
202 std::chrono::steady_clock::now().time_since_epoch()).count();
203 }
204 RS_TRACE_NAME_FMT("RSHardwareThread::CommitAndReleaseLayers rate: %u, now: %" PRIu64 ", " \
205 "vsyncId: %" PRIu64 ", size: %zu", currentRate, param.frameTimestamp, param.vsyncId, layers.size());
206 RS_LOGD("RSHardwareThread::CommitAndReleaseLayers rate:%{public}u, " \
207 "now:%{public}" PRIu64 ", vsyncId:%{public}" PRIu64 ", size:%{public}zu",
208 currentRate, param.frameTimestamp, param.vsyncId, layers.size());
209 ExecuteSwitchRefreshRate(param.rate);
210 PerformSetActiveMode(output, param.frameTimestamp, param.constraintRelativeTime);
211 AddRefreshRateCount();
212 output->SetLayerInfo(layers);
213 if (output->IsDeviceValid()) {
214 hdiBackend_->Repaint(output);
215 }
216 output->ReleaseLayers(releaseFence_);
217 RSBaseRenderUtil::DecAcquiredBufferCount();
218 RSUniRenderThread::Instance().NotifyDisplayNodeBufferReleased();
219 if (hasGameScene) {
220 endTimeNs = std::chrono::duration_cast<std::chrono::nanoseconds>(
221 std::chrono::steady_clock::now().time_since_epoch()).count();
222 FrameReport::GetInstance().SetLastSwapBufferTime(endTimeNs - startTimeNs);
223 }
224 unExecuteTaskNum_--;
225 RS_LOGD("RSHardwareThread::CommitAndReleaseData unExecuteTaskNum_:%{public}d,"
226 " HARDWARE_THREAD_TASK_NUM:%{public}d", unExecuteTaskNum_.load(), HARDWARE_THREAD_TASK_NUM);
227 if (unExecuteTaskNum_ <= HARDWARE_THREAD_TASK_NUM) {
228 RSMainThread::Instance()->NotifyHardwareThreadCanExecuteTask();
229 }
230 };
231 RSBaseRenderUtil::IncAcquiredBufferCount();
232 unExecuteTaskNum_++;
233 RSMainThread::Instance()->SetHardwareTaskNum(unExecuteTaskNum_.load());
234 RS_LOGI_IF(DEBUG_COMPOSER,
235 "RSHardwareThread::CommitAndReleaseData hgmCore's LtpoEnabled is %{public}d", hgmCore.GetLtpoEnabled());
236 int64_t currTime = SystemTime();
237 if (IsDelayRequired(hgmCore, param, hasGameScene)) {
238 CalculateDelayTime(hgmCore, param, currentRate, currTime);
239 }
240 // We need to ensure the order of composition frames, postTaskTime(n + 1) must > postTaskTime(n),
241 // and we give a delta time more between two composition tasks.
242 int64_t currCommitTime = currTime + delayTime_ * NS_MS_UNIT_CONVERSION;
243 if (currCommitTime <= lastCommitTime_) {
244 delayTime_ = delayTime_ +
245 std::round((lastCommitTime_ - currCommitTime) * 1.0f / NS_MS_UNIT_CONVERSION) +
246 COMMIT_DELTA_TIME;
247 RS_LOGD("RSHardwareThread::CommitAndReleaseLayers vsyncId: %{public}" PRIu64 ", " \
248 "update delayTime: %{public}" PRId64 ", currCommitTime: %{public}" PRId64 ", " \
249 "lastCommitTime: %{public}" PRId64, param.vsyncId, delayTime_, currCommitTime, lastCommitTime_);
250 RS_TRACE_NAME_FMT("update delayTime: %" PRId64 ", currCommitTime: %" PRId64 ", lastCommitTime: %" PRId64 "",
251 delayTime_, currCommitTime, lastCommitTime_);
252 }
253 if (delayTime_ < 0 || delayTime_ >= MAX_DELAY_TIME) {
254 delayTime_ = 0;
255 }
256 lastCommitTime_ = currTime + delayTime_ * NS_MS_UNIT_CONVERSION;
257 PostDelayTask(task, delayTime_);
258
259 for (const auto& layer : layers) {
260 if (layer == nullptr || layer->GetClearCacheSet().empty()) {
261 continue;
262 }
263 // Remove image caches when their SurfaceNode has gobackground/cleancache.
264 RSTaskMessage::RSTask clearTask = [this, cacheset = layer->GetClearCacheSet()]() {
265 if (uniRenderEngine_ != nullptr) {
266 uniRenderEngine_->ClearCacheSet(cacheset);
267 }
268 };
269 PostDelayTask(clearTask, delayTime_);
270 }
271 }
272
IsDelayRequired(OHOS::Rosen::HgmCore & hgmCore,RefreshRateParam param,bool hasGameScene)273 bool RSHardwareThread::IsDelayRequired(OHOS::Rosen::HgmCore& hgmCore, RefreshRateParam param, bool hasGameScene)
274 {
275 if (param.isForceRefresh) {
276 RS_LOGD("RSHardwareThread::CommitAndReleaseLayers in Force Refresh");
277 RS_TRACE_NAME("CommitAndReleaseLayers in Force Refresh");
278 return false;
279 }
280
281 if (!hgmCore.GetLtpoEnabled()) {
282 if (!hgmCore.IsDelayMode()) {
283 return false;
284 }
285 if (hasGameScene) {
286 RS_LOGD("RSHardwareThread::CommitAndReleaseLayers in Game Scene");
287 RS_TRACE_NAME("CommitAndReleaseLayers in Game Scene");
288 return false;
289 }
290 }
291 return true;
292 }
293
CalculateDelayTime(OHOS::Rosen::HgmCore & hgmCore,RefreshRateParam param,uint32_t currentRate,int64_t currTime)294 void RSHardwareThread::CalculateDelayTime(OHOS::Rosen::HgmCore& hgmCore, RefreshRateParam param, uint32_t currentRate,
295 int64_t currTime)
296 {
297 int64_t frameOffset = 0;
298 int64_t vsyncOffset = 0;
299 int64_t pipelineOffset = 0;
300 int64_t expectCommitTime = 0;
301 int64_t idealPeriod = hgmCore.GetIdealPeriod(currentRate);
302 int64_t period = CreateVSyncSampler()->GetHardwarePeriod();
303 uint64_t dvsyncOffset = RSMainThread::Instance()->GetRealTimeOffsetOfDvsync(param.frameTimestamp);
304 int64_t compositionTime = period;
305
306 if (!hgmCore.GetLtpoEnabled()) {
307 vsyncOffset = UNI_RENDER_VSYNC_OFFSET_DELAY_MODE;
308 // 2 period for draw and composition, pipelineOffset = 2 * period
309 frameOffset = 2 * period + vsyncOffset;
310 } else {
311 if (idealPeriod == PERIOD_60_HZ) {
312 vsyncOffset = CreateVSyncGenerator()->GetVSyncOffset();
313 }
314 pipelineOffset = hgmCore.GetPipelineOffset();
315 frameOffset = pipelineOffset + vsyncOffset + static_cast<int64_t>(dvsyncOffset);
316 }
317 expectCommitTime = param.actualTimestamp + frameOffset - compositionTime - RESERVE_TIME;
318 int64_t diffTime = expectCommitTime - currTime;
319 if (diffTime > 0 && period > 0) {
320 delayTime_ = std::round(diffTime * 1.0f / NS_MS_UNIT_CONVERSION);
321 }
322 RS_TRACE_NAME_FMT("CalculateDelayTime pipelineOffset: %" PRId64 ", actualTimestamp: %" PRId64 ", " \
323 "expectCommitTime: %" PRId64 ", currTime: %" PRId64 ", diffTime: %" PRId64 ", delayTime: %" PRId64 ", " \
324 "frameOffset: %" PRId64 ", dvsyncOffset: %" PRIu64 ", vsyncOffset: %" PRId64 ", idealPeriod: %" PRId64 ", " \
325 "period: %" PRId64 "",
326 pipelineOffset, param.actualTimestamp, expectCommitTime, currTime, diffTime, delayTime_,
327 frameOffset, dvsyncOffset, vsyncOffset, idealPeriod, period);
328 RS_LOGD("RSHardwareThread::CalculateDelayTime period:%{public}" PRIu64 " delayTime:%{public}" PRIu64 "",
329 period, delayTime_);
330 }
331
GetRefreshRateParam()332 RefreshRateParam RSHardwareThread::GetRefreshRateParam()
333 {
334 // need to sync the hgm data from main thread.
335 // Temporary sync the timestamp to fix the duplicate time stamp issue.
336 auto& hgmCore = OHOS::Rosen::HgmCore::Instance();
337 bool directComposition = hgmCore.GetDirectCompositionFlag();
338 if (directComposition) {
339 hgmCore.SetDirectCompositionFlag(false);
340 }
341 RefreshRateParam param;
342 if (directComposition) {
343 param = {
344 .rate = hgmCore.GetPendingScreenRefreshRate(),
345 .frameTimestamp = hgmCore.GetCurrentTimestamp(),
346 .actualTimestamp = hgmCore.GetActualTimestamp(),
347 .vsyncId = hgmCore.GetVsyncId(),
348 .constraintRelativeTime = hgmCore.GetPendingConstraintRelativeTime(),
349 .isForceRefresh = hgmCore.GetForceRefreshFlag(),
350 };
351 } else {
352 param = {
353 .rate = RSUniRenderThread::Instance().GetPendingScreenRefreshRate(),
354 .frameTimestamp = RSUniRenderThread::Instance().GetCurrentTimestamp(),
355 .actualTimestamp = RSUniRenderThread::Instance().GetActualTimestamp(),
356 .vsyncId = RSUniRenderThread::Instance().GetVsyncId(),
357 .constraintRelativeTime = RSUniRenderThread::Instance().GetPendingConstraintRelativeTime(),
358 .isForceRefresh = RSUniRenderThread::Instance().GetForceRefreshFlag(),
359 };
360 }
361 return param;
362 }
363
OnScreenVBlankIdleCallback(ScreenId screenId,uint64_t timestamp)364 void RSHardwareThread::OnScreenVBlankIdleCallback(ScreenId screenId, uint64_t timestamp)
365 {
366 RS_TRACE_NAME_FMT("RSHardwareThread::OnScreenVBlankIdleCallback screenId: %d now: %lu", screenId, timestamp);
367 vblankIdleCorrector_.SetScreenVBlankIdle(screenId);
368 }
369
ExecuteSwitchRefreshRate(uint32_t refreshRate)370 void RSHardwareThread::ExecuteSwitchRefreshRate(uint32_t refreshRate)
371 {
372 static bool refreshRateSwitch = system::GetBoolParameter("persist.hgm.refreshrate.enabled", true);
373 if (!refreshRateSwitch) {
374 RS_LOGD("RSHardwareThread: refreshRateSwitch is off, currRefreshRate is %{public}d", refreshRate);
375 return;
376 }
377
378 static ScreenId lastScreenId = 12345; // init value diff with any real screen id
379 auto screenManager = CreateOrGetScreenManager();
380 auto& hgmCore = OHOS::Rosen::HgmCore::Instance();
381 if (hgmCore.GetFrameRateMgr() == nullptr) {
382 RS_LOGD("FrameRateMgr is null");
383 return;
384 }
385 auto screenRefreshRateImme = hgmCore.GetScreenRefreshRateImme();
386 if (screenRefreshRateImme > 0) {
387 RS_LOGD("ExecuteSwitchRefreshRate:rate change: %{public}u -> %{public}u", refreshRate, screenRefreshRateImme);
388 refreshRate = screenRefreshRateImme;
389 }
390 ScreenId id = hgmCore.GetFrameRateMgr()->GetCurScreenId();
391 if (refreshRate != hgmCore.GetScreenCurrentRefreshRate(id) || lastScreenId != id) {
392 RS_LOGI("RSHardwareThread::CommitAndReleaseLayers screenId %{public}d refreshRate %{public}d",
393 static_cast<int>(id), refreshRate);
394 lastScreenId = id;
395 int32_t status = hgmCore.SetScreenRefreshRate(id, 0, refreshRate);
396 if (status < EXEC_SUCCESS) {
397 RS_LOGD("RSHardwareThread: failed to set refreshRate %{public}d, screenId %{public}" PRIu64 "", refreshRate,
398 id);
399 }
400 }
401 }
402
PerformSetActiveMode(OutputPtr output,uint64_t timestamp,uint64_t constraintRelativeTime)403 void RSHardwareThread::PerformSetActiveMode(OutputPtr output, uint64_t timestamp, uint64_t constraintRelativeTime)
404 {
405 auto &hgmCore = OHOS::Rosen::HgmCore::Instance();
406 auto screenManager = CreateOrGetScreenManager();
407 if (screenManager == nullptr) {
408 RS_LOGE("RSHardwareThread CreateOrGetScreenManager fail.");
409 return;
410 }
411
412 vblankIdleCorrector_.ProcessScreenConstraint(timestamp, constraintRelativeTime);
413 HgmRefreshRates newRate = RSSystemProperties::GetHgmRefreshRatesEnabled();
414 if (hgmRefreshRates_ != newRate) {
415 hgmRefreshRates_ = newRate;
416 hgmCore.SetScreenRefreshRate(screenManager->GetDefaultScreenId(), 0, static_cast<int32_t>(hgmRefreshRates_));
417 }
418
419 std::unique_ptr<std::unordered_map<ScreenId, int32_t>> modeMap(hgmCore.GetModesToApply());
420 if (modeMap == nullptr) {
421 return;
422 }
423
424 RS_TRACE_NAME_FMT("RSHardwareThread::PerformSetActiveMode setting active mode. rate: %d",
425 HgmCore::Instance().GetScreenCurrentRefreshRate(HgmCore::Instance().GetActiveScreenId()));
426 for (auto mapIter = modeMap->begin(); mapIter != modeMap->end(); ++mapIter) {
427 ScreenId id = mapIter->first;
428 int32_t modeId = mapIter->second;
429
430 auto supportedModes = screenManager->GetScreenSupportedModes(id);
431 for (auto mode : supportedModes) {
432 RS_OPTIONAL_TRACE_NAME_FMT("RSHardwareThread check modes w: %d, h: %d, rate: %d, id: %d",
433 mode.GetScreenWidth(), mode.GetScreenHeight(), mode.GetScreenRefreshRate(), mode.GetScreenModeId());
434 }
435
436 screenManager->SetScreenActiveMode(id, modeId);
437 auto pendingPeriod = hgmCore.GetIdealPeriod(hgmCore.GetScreenCurrentRefreshRate(id));
438 int64_t pendingTimestamp = static_cast<int64_t>(timestamp);
439 if (hdiBackend_) {
440 hdiBackend_->SetPendingMode(output, pendingPeriod, pendingTimestamp);
441 hdiBackend_->StartSample(output);
442 }
443 }
444 }
445
OnPrepareComplete(sptr<Surface> & surface,const PrepareCompleteParam & param,void * data)446 void RSHardwareThread::OnPrepareComplete(sptr<Surface>& surface,
447 const PrepareCompleteParam& param, void* data)
448 {
449 // unused data.
450 (void)(data);
451
452 if (!param.needFlushFramebuffer) {
453 return;
454 }
455
456 if (redrawCb_ != nullptr) {
457 redrawCb_(surface, param.layers, param.screenId);
458 }
459 }
460
ClearFrameBuffers(OutputPtr output)461 GSError RSHardwareThread::ClearFrameBuffers(OutputPtr output)
462 {
463 if (output == nullptr) {
464 RS_LOGE("Clear frame buffers failed for the output is nullptr");
465 return GSERROR_INVALID_ARGUMENTS;
466 }
467 RS_TRACE_NAME("RSHardwareThread::ClearFrameBuffers");
468 if (uniRenderEngine_ != nullptr) {
469 uniRenderEngine_->ResetCurrentContext();
470 }
471 #ifdef RS_ENABLE_VK
472 if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN) {
473 auto frameBufferSurface = std::static_pointer_cast<RSSurfaceOhosVulkan>(frameBufferSurfaceOhos_);
474 if (frameBufferSurface) {
475 frameBufferSurface->WaitSurfaceClear();
476 }
477 }
478 #endif
479 return output->ClearFrameBuffer();
480 }
481
CreateFrameBufferSurfaceOhos(const sptr<Surface> & surface)482 std::shared_ptr<RSSurfaceOhos> RSHardwareThread::CreateFrameBufferSurfaceOhos(const sptr<Surface>& surface)
483 {
484 std::shared_ptr<RSSurfaceOhos> rsSurface = nullptr;
485 #if (defined RS_ENABLE_GL) && (defined RS_ENABLE_EGLIMAGE)
486 if (RSSystemProperties::GetGpuApiType() == GpuApiType::OPENGL) {
487 rsSurface = std::make_shared<RSSurfaceOhosGl>(surface);
488 }
489 #endif
490 #if (defined RS_ENABLE_VK)
491 if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN) {
492 rsSurface = std::make_shared<RSSurfaceOhosVulkan>(surface);
493 }
494 #endif
495 RS_LOGD("RSHardwareThread::Redraw: CreateFrameBufferSurfaceOhos.");
496 return rsSurface;
497 }
498
RedrawScreenRCD(RSPaintFilterCanvas & canvas,const std::vector<LayerInfoPtr> & layers)499 void RSHardwareThread::RedrawScreenRCD(RSPaintFilterCanvas& canvas, const std::vector<LayerInfoPtr>& layers)
500 {
501 RS_TRACE_NAME("RSHardwareThread::RedrawScreenRCD");
502 using RSRcdManager = RSSingleton<RoundCornerDisplayManager>;
503 std::vector<std::pair<NodeId, RoundCornerDisplayManager::RCDLayerType>> rcdLayerInfoList;
504 for (const auto& layer : layers) {
505 if (layer == nullptr) {
506 continue;
507 }
508 auto layerSurface = layer->GetSurface();
509 if (layerSurface != nullptr) {
510 auto rcdlayerInfo = RSRcdManager::GetInstance().GetLayerPair(layerSurface->GetName());
511 if (rcdlayerInfo.second != RoundCornerDisplayManager::RCDLayerType::INVALID) {
512 rcdLayerInfoList.push_back(rcdlayerInfo);
513 continue;
514 }
515 } else {
516 RS_LOGE("RSHardwareThread::RedrawScreenRCD layerSurface is nullptr");
517 continue;
518 }
519 }
520
521 if (RSRcdManager::GetInstance().GetRcdEnable()) {
522 RSRcdManager::GetInstance().DrawRoundCorner(rcdLayerInfoList, &canvas);
523 }
524 }
525
Redraw(const sptr<Surface> & surface,const std::vector<LayerInfoPtr> & layers,uint32_t screenId)526 void RSHardwareThread::Redraw(const sptr<Surface>& surface, const std::vector<LayerInfoPtr>& layers, uint32_t screenId)
527 {
528 RS_TRACE_NAME("RSHardwareThread::Redraw");
529 if (surface == nullptr || uniRenderEngine_ == nullptr) {
530 RS_LOGE("RSHardwareThread::Redraw: surface or uniRenderEngine is null.");
531 return;
532 }
533 bool isProtected = false;
534 #ifdef RS_ENABLE_VK
535 if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
536 RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
537 if (RSSystemProperties::GetDrmEnabled() && RSMainThread::Instance()->GetDeviceType() != DeviceType::PC) {
538 for (const auto& layer : layers) {
539 if (layer && layer->GetBuffer() && (layer->GetBuffer()->GetUsage() & BUFFER_USAGE_PROTECTED)) {
540 isProtected = true;
541 break;
542 }
543 }
544 if (RSSystemProperties::IsUseVulkan()) {
545 RsVulkanContext::GetSingleton().SetIsProtected(isProtected);
546 }
547 } else {
548 RsVulkanContext::GetSingleton().SetIsProtected(false);
549 }
550 }
551 #endif
552
553 RS_LOGD("RsDebug RSHardwareThread::Redraw flush frame buffer start");
554 bool forceCPU = RSBaseRenderEngine::NeedForceCPU(layers);
555 auto screenManager = CreateOrGetScreenManager();
556 if (screenManager == nullptr) {
557 RS_LOGE("RSHardwareThread::Redraw: screenManager is null.");
558 return;
559 }
560 auto screenInfo = screenManager->QueryScreenInfo(screenId);
561 std::shared_ptr<Drawing::ColorSpace> drawingColorSpace = nullptr;
562 #ifdef USE_VIDEO_PROCESSING_ENGINE
563 GraphicColorGamut colorGamut = ComputeTargetColorGamut(layers);
564 GraphicPixelFormat pixelFormat = ComputeTargetPixelFormat(layers);
565 auto renderFrameConfig = RSBaseRenderUtil::GetFrameBufferRequestConfig(screenInfo,
566 true, isProtected, colorGamut, pixelFormat);
567 drawingColorSpace = RSBaseRenderEngine::ConvertColorGamutToDrawingColorSpace(colorGamut);
568 // set color space to surface buffer metadata
569 using namespace HDI::Display::Graphic::Common::V1_0;
570 CM_ColorSpaceType colorSpace = CM_SRGB_FULL;
571 if (ConvertColorGamutToSpaceType(colorGamut, colorSpace)) {
572 if (surface->SetUserData("ATTRKEY_COLORSPACE_INFO", std::to_string(colorSpace)) != GSERROR_OK) {
573 RS_LOGD("RSHardwareThread::Redraw set user data failed");
574 }
575 }
576 #else
577 auto renderFrameConfig = RSBaseRenderUtil::GetFrameBufferRequestConfig(screenInfo, true, isProtected);
578 #endif
579 // override redraw frame buffer with physical screen resolution.
580 renderFrameConfig.width = static_cast<int32_t>(screenInfo.phyWidth);
581 renderFrameConfig.height = static_cast<int32_t>(screenInfo.phyHeight);
582 if (frameBufferSurfaceOhos_ == nullptr) {
583 frameBufferSurfaceOhos_ = CreateFrameBufferSurfaceOhos(surface);
584 }
585 FrameContextConfig frameContextConfig = {isProtected, false};
586 if (RSSystemProperties::GetVkQueueDividedEnable()) {
587 frameContextConfig.independentContext = true;
588 }
589 auto renderFrame = uniRenderEngine_->RequestFrame(frameBufferSurfaceOhos_, renderFrameConfig,
590 forceCPU, true, frameContextConfig);
591 if (renderFrame == nullptr) {
592 RS_LOGE("RsDebug RSHardwareThread::Redraw failed to request frame.");
593 return;
594 }
595 auto canvas = renderFrame->GetCanvas();
596 if (canvas == nullptr) {
597 RS_LOGE("RsDebug RSHardwareThread::Redraw canvas is nullptr.");
598 return;
599 }
600 #ifdef RS_ENABLE_VK
601 if (RSSystemProperties::IsUseVulkan()) {
602 canvas->Clear(Drawing::Color::COLOR_TRANSPARENT);
603 }
604 #endif
605
606 #ifdef USE_VIDEO_PROCESSING_ENGINE
607 uniRenderEngine_->DrawLayers(*canvas, layers, false, screenInfo, colorGamut);
608 #else
609 uniRenderEngine_->DrawLayers(*canvas, layers, false, screenInfo);
610 #endif
611 RedrawScreenRCD(*canvas, layers);
612 renderFrame->Flush();
613 RS_LOGD("RsDebug RSHardwareThread::Redraw flush frame buffer end");
614 }
615
AddRefreshRateCount()616 void RSHardwareThread::AddRefreshRateCount()
617 {
618 auto screenManager = CreateOrGetScreenManager();
619 if (screenManager == nullptr) {
620 RS_LOGE("RSHardwareThread::AddRefreshRateCount screenManager is nullptr");
621 return;
622 }
623 ScreenId id = screenManager->GetDefaultScreenId();
624 auto& hgmCore = OHOS::Rosen::HgmCore::Instance();
625 uint32_t currentRefreshRate = hgmCore.GetScreenCurrentRefreshRate(id);
626 auto [iter, success] = refreshRateCounts_.try_emplace(currentRefreshRate, 1);
627 if (!success) {
628 iter->second++;
629 }
630 RSRealtimeRefreshRateManager::Instance().CountRealtimeFrame();
631
632 auto frameRateMgr = hgmCore.GetFrameRateMgr();
633 if (frameRateMgr == nullptr) {
634 return;
635 }
636 frameRateMgr->GetTouchManager().HandleRsFrame();
637 }
638
SubScribeSystemAbility()639 void RSHardwareThread::SubScribeSystemAbility()
640 {
641 RS_LOGI("%{public}s", __func__);
642 sptr<ISystemAbilityManager> systemAbilityManager =
643 SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
644 if (!systemAbilityManager) {
645 RS_LOGE("%{public}s failed to get system ability manager client", __func__);
646 return;
647 }
648 std::string threadName = "RSHardwareThread";
649 std::string strUid = std::to_string(getuid());
650 std::string strPid = std::to_string(getpid());
651 std::string strTid = std::to_string(gettid());
652
653 saStatusChangeListener_ = new (std::nothrow)VSyncSystemAbilityListener(threadName, strUid, strPid, strTid);
654 int32_t ret = systemAbilityManager->SubscribeSystemAbility(RES_SCHED_SYS_ABILITY_ID, saStatusChangeListener_);
655 if (ret != ERR_OK) {
656 RS_LOGE("%{public}s subscribe system ability %{public}d failed.", __func__, RES_SCHED_SYS_ABILITY_ID);
657 saStatusChangeListener_ = nullptr;
658 }
659 }
660
661 #ifdef USE_VIDEO_PROCESSING_ENGINE
ComputeTargetColorGamut(const std::vector<LayerInfoPtr> & layers)662 GraphicColorGamut RSHardwareThread::ComputeTargetColorGamut(const std::vector<LayerInfoPtr>& layers)
663 {
664 using namespace HDI::Display::Graphic::Common::V1_0;
665 GraphicColorGamut colorGamut = GRAPHIC_COLOR_GAMUT_SRGB;
666 for (auto& layer : layers) {
667 if (layer == nullptr) {
668 RS_LOGE("RSHardwareThread::ComputeTargetColorGamut layer is nullptr");
669 continue;
670 }
671 auto buffer = layer->GetBuffer();
672 if (buffer == nullptr) {
673 RS_LOGW("RSHardwareThread::ComputeTargetColorGamut The buffer of layer is nullptr");
674 continue;
675 }
676
677 CM_ColorSpaceInfo colorSpaceInfo;
678 if (MetadataHelper::GetColorSpaceInfo(buffer, colorSpaceInfo) != GSERROR_OK) {
679 RS_LOGD("RSHardwareThread::ComputeTargetColorGamut Get color space failed");
680 continue;
681 }
682
683 if (colorSpaceInfo.primaries != COLORPRIMARIES_SRGB) {
684 colorGamut = GRAPHIC_COLOR_GAMUT_DISPLAY_P3;
685 break;
686 }
687 }
688
689 return colorGamut;
690 }
691
ComputeTargetPixelFormat(const std::vector<LayerInfoPtr> & layers)692 GraphicPixelFormat RSHardwareThread::ComputeTargetPixelFormat(const std::vector<LayerInfoPtr>& layers)
693 {
694 using namespace HDI::Display::Graphic::Common::V1_0;
695 GraphicPixelFormat pixelFormat = GRAPHIC_PIXEL_FMT_RGBA_8888;
696 for (auto& layer : layers) {
697 if (layer == nullptr) {
698 continue;
699 }
700 auto buffer = layer->GetBuffer();
701 if (buffer == nullptr) {
702 RS_LOGW("RSHardwareThread::ComputeTargetPixelFormat The buffer of layer is nullptr");
703 continue;
704 }
705
706 auto bufferPixelFormat = buffer->GetFormat();
707 if (bufferPixelFormat == GRAPHIC_PIXEL_FMT_RGBA_1010102 ||
708 bufferPixelFormat == GRAPHIC_PIXEL_FMT_YCBCR_P010 ||
709 bufferPixelFormat == GRAPHIC_PIXEL_FMT_YCRCB_P010) {
710 pixelFormat = GRAPHIC_PIXEL_FMT_RGBA_1010102;
711 RS_LOGD("RSHardwareThread::ComputeTargetPixelFormat pixelformat is set to 1010102 for 10bit buffer");
712 break;
713 }
714 }
715
716 return pixelFormat;
717 }
718
ConvertColorGamutToSpaceType(const GraphicColorGamut & colorGamut,HDI::Display::Graphic::Common::V1_0::CM_ColorSpaceType & colorSpaceType)719 bool RSHardwareThread::ConvertColorGamutToSpaceType(const GraphicColorGamut& colorGamut,
720 HDI::Display::Graphic::Common::V1_0::CM_ColorSpaceType& colorSpaceType)
721 {
722 using namespace HDI::Display::Graphic::Common::V1_0;
723 static const std::map<GraphicColorGamut, CM_ColorSpaceType> RS_TO_COMMON_COLOR_SPACE_TYPE_MAP {
724 {GRAPHIC_COLOR_GAMUT_STANDARD_BT601, CM_BT601_EBU_FULL},
725 {GRAPHIC_COLOR_GAMUT_STANDARD_BT709, CM_BT709_FULL},
726 {GRAPHIC_COLOR_GAMUT_SRGB, CM_SRGB_FULL},
727 {GRAPHIC_COLOR_GAMUT_ADOBE_RGB, CM_ADOBERGB_FULL},
728 {GRAPHIC_COLOR_GAMUT_DISPLAY_P3, CM_P3_FULL},
729 {GRAPHIC_COLOR_GAMUT_BT2020, CM_DISPLAY_BT2020_SRGB},
730 {GRAPHIC_COLOR_GAMUT_BT2100_PQ, CM_BT2020_PQ_FULL},
731 {GRAPHIC_COLOR_GAMUT_BT2100_HLG, CM_BT2020_HLG_FULL},
732 {GRAPHIC_COLOR_GAMUT_DISPLAY_BT2020, CM_DISPLAY_BT2020_SRGB},
733 };
734
735 if (RS_TO_COMMON_COLOR_SPACE_TYPE_MAP.find(colorGamut) == RS_TO_COMMON_COLOR_SPACE_TYPE_MAP.end()) {
736 return false;
737 }
738
739 colorSpaceType = RS_TO_COMMON_COLOR_SPACE_TYPE_MAP.at(colorGamut);
740 return true;
741 }
742 #endif
743 }
744