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