• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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