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