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