diff --git a/rosen/modules/render_service/BUILD.gn b/rosen/modules/render_service/BUILD.gn index 65c98d9fb2e8650543f897fb278e02518bb01925..a10ff9b70db468c4e4484ad698e057f279f75eb5 100644 --- a/rosen/modules/render_service/BUILD.gn +++ b/rosen/modules/render_service/BUILD.gn @@ -281,6 +281,13 @@ ohos_shared_library("librender_service") { "core/pipeline/render_thread/rs_uni_render_util.cpp", "core/pipeline/render_thread/rs_uni_render_virtual_processor.cpp", ] + #composer + sources += [ + "composer/pipeline/src/rs_render_composer_agent.cpp", + "composer/pipeline/src/rs_render_composer_context.cpp", + "composer/pipeline/src/rs_render_composer_manager.cpp", + "composer/pipeline/src/rs_render_composer.cpp", + ] } if (graphic_2d_feature_enable_rdo) { @@ -339,6 +346,7 @@ ohos_shared_library("librender_service") { } include_dirs = [ + "composer/pipeline/include", "core", "core/feature_cfg", "core/feature_cfg/feature_param", diff --git a/rosen/modules/render_service/composer/pipeline/include/rs_render_composer.h b/rosen/modules/render_service/composer/pipeline/include/rs_render_composer.h new file mode 100644 index 0000000000000000000000000000000000000000..3672e8d2fbd9ce632a15c64274f6affa186d9cee --- /dev/null +++ b/rosen/modules/render_service/composer/pipeline/include/rs_render_composer.h @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2025-2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef RS_RENDER_COMPOSER_H +#define RS_RENDER_COMPOSER_H +#include +#include + +#include "event_handler.h" +#include "feature/hyper_graphic_manager/hgm_hardware_utils.h" +#include "hdi_backend.h" +#include "hgm_core.h" +#include "pipeline/main_thread/rs_main_thread.h" +#include "rs_render_composer_context.h" +#ifdef RES_SCHED_ENABLE +#include "vsync_system_ability_listener.h" +#endif + +namespace OHOS::Rosen { +using UniFallbackCallback = std::function& surface, const std::vector& layers, + uint32_t screenId)>; +class ScheduledTask; +class RSRenderComposer { +public: + RSRenderComposer(const OutputPtr& output); + ~RSRenderComposer() = default; + + void UpdateLayersAndComposerFrame(); + int32_t GetHardwareThreadTid() const; + uint32_t GetUnExecuteTaskNum(); + void PostTask(const std::function& task); + void PostSyncTask(const std::function& task); + void PostDelayTask(const std::function& task, int64_t delayTime); +private: + // 维护layer + void AddComposerLayer(); + void UpdateComposerLayer(); + void DeleteComposerLayer(); + + // 合成 + void PrepareComposeFrame(RefreshRateParam& param, uint32_t& currentRate, bool& hasGameScene, + ScreenId& curScreenId, int64_t& delayTime); + void ProcessComposeFrame(RefreshRateParam param, uint32_t currentRate, bool hasGameScene, ScreenId curScreenId); + + void init(const OutputPtr& output); + void Redraw(const sptr& surface, const std::vector& layers, uint32_t screenId); + void OnPrepareComplete(sptr& surface, const PrepareCompleteParam& param, void* data); + void UpdateDelayTime(OHOS::Rosen::HgmCore& hgmCore, RefreshRateParam param, + uint32_t currentRate, bool hasGameScene); + bool IsDelayRequired(OHOS::Rosen::HgmCore& hgmCore, RefreshRateParam param, + const OutputPtr& output, bool hasGameScene); + void CalculateDelayTime(OHOS::Rosen::HgmCore& hgmCore, RefreshRateParam param, + uint32_t currentRate, int64_t currTime); + int32_t AdaptiveModeStatus(const OutputPtr& output); + void EndCheck(RSTimer timer); + int64_t GetCurTimeCount(); + std::string GetSurfaceNameInLayers(const std::vector& layers); + std::string GetSurfaceNameInLayersForTrace(const std::vector& layers); + void ChangeLayersForActiveRectOutside(std::vector& layers, ScreenId screenId); + void AddRefreshRateCount(const OutputPtr& output); + void RecordTimestamp(const std::vector& layers); + bool IsDropDirtyFrame(const std::vector& layerInfos, uint32_t screenId); +#ifdef USE_VIDEO_PROCESSING_ENGINE + static GraphicColorGamut ComputeTargetColorGamut(const std::vector& layers); + static GraphicPixelFormat ComputeTargetPixelFormat(const std::vector& layers); + static bool ConvertColorGamutToSpaceType(const GraphicColorGamut& colorGamut, + HDI::Display::Graphic::Common::V1_0::CM_ColorSpaceType& colorSpaceInfo); +#endif + void RedrawScreenRCD(RSPaintFilterCanvas& canvas, const std::vector& layers); + void ContextRegisterPostTask(); +#ifdef RES_SCHED_ENABLE + void SubScribeSystemAbility(); + sptr saStatusChangeListener_ = nullptr; +#endif + std::shared_ptr CreateFrameBufferSurfaceOhos(const sptr& surface); + + void IncUnExecuteTaskNum(); + void SubUnExecuteTaskNum(); + + template> + std::future ScheduleTask(Task&& task) + { + auto [scheduledTask, taskFuture] = Detail::ScheduledTask::Create(std::forward(task)); +#ifdef RS_ENABLE_GPU + PostTask([t(std::move(scheduledTask))]() { t->Run(); }); +#endif + return std::move(taskFuture); + } + + std::shared_ptr runner_ = nullptr; + std::shared_ptr handler_ = nullptr; + HdiBackend* hdiBackend_ = nullptr; + OutputPtr hdiOutput_; + sptr releaseFence_ = SyncFence::InvalidFence(); + int32_t threadTid_ = -1; + ScreenId screenId_; + std::shared_ptr rsRenderComposerContext_; + std::shared_ptr uniRenderEngine_; + HgmHardwareUtils hgmHardwareUtils_; + UniFallbackCallback redrawCb_; + std::mutex preAllocMutex_; + std::mutex surfaceMutex_; + std::mutex frameBufferSurfaceOhosMapMutex_; + std::unordered_map> frameBufferSurfaceOhosMap_; + int64_t delayTime_ = 0; + int64_t lastCommitTime_ = 0; + std::atomic unExecuteTaskNum_ = 0; + int hardwareCount_ = 0; + ExceptionCheck exceptionCheck_; + std::map refreshRateCounts_; + int64_t lastActualTime_ = 0; + int64_t intervalTimePoints_ = 0; +}; +} // namespace OHOS +#endif // RS_RENDER_COMPOSER_H \ No newline at end of file diff --git a/rosen/modules/render_service/composer/pipeline/include/rs_render_composer_agent.h b/rosen/modules/render_service/composer/pipeline/include/rs_render_composer_agent.h new file mode 100644 index 0000000000000000000000000000000000000000..fa3ede650c5accab03532272c5719bd24ea23e0f --- /dev/null +++ b/rosen/modules/render_service/composer/pipeline/include/rs_render_composer_agent.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2025-2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RS_RENDER_COMPOSER_THREAD_AGENT_H +#define RS_RENDER_COMPOSER_THREAD_AGENT_H + +#include "rs_render_composer.h" + +namespace OHOS::Rosen { +class RSRenderComposerAgent { +public: + RSRenderComposerAgent(std::shared_ptr rsRenderComposer); + ~RSRenderComposerAgent() = default; + + void UpdateLayersAndComposerFrame(); +private: + std::shared_ptr rsRenderComposer_; +}; +} // namespace OHOS +#endif // RS_RENDER_COMPOSER_THREAD_AGENT_H \ No newline at end of file diff --git a/rosen/modules/render_service/composer/pipeline/include/rs_render_composer_context.h b/rosen/modules/render_service/composer/pipeline/include/rs_render_composer_context.h new file mode 100644 index 0000000000000000000000000000000000000000..22db5785b4cd623538664d1e4dbd56722f67f169 --- /dev/null +++ b/rosen/modules/render_service/composer/pipeline/include/rs_render_composer_context.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2025-2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RS_RENDER_COMPOSER_CONTEXT_H +#define RS_RENDER_COMPOSER_CONTEXT_H + +#include "common/rs_common_def.h" +#include "hdi_layer.h" +#include "hdi_layer_info.h" +// #include "rs_render_layer.h" + +namespace OHOS::Rosen { +class RSRenderComposerContext { +public: + RSRenderComposerContext() = default; + ~RSRenderComposerContext() = default; + + // 维护layer + void AddComposerLayer(); + void UpdateComposerLayer(); + void DeleteComposerLayer(); + + // std::unordered_map>& GetLayersMap(); + std::vector& GetLayersVec(); + +private: + // std::unordered_map> layersMap_; + std::vector layersVec_; +}; +} // namespace OHOS +#endif // RS_RENDER_COMPOSER_CONTEXT_H \ No newline at end of file diff --git a/rosen/modules/render_service/composer/pipeline/include/rs_render_composer_manager.h b/rosen/modules/render_service/composer/pipeline/include/rs_render_composer_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..15d2ce6f0fe2f7eecca372bbcc33166eca6fe442 --- /dev/null +++ b/rosen/modules/render_service/composer/pipeline/include/rs_render_composer_manager.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2025-2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RS_RENDER_COMPOSER_MANAGER_H +#define RS_RENDER_COMPOSER_MANAGER_H + +#include "rs_render_composer.h" + +namespace OHOS::Rosen { +class RSRenderComposerManager { +public: + RSRenderComposerManager(std::shared_ptr& handler); + ~RSRenderComposerManager() = default; + void OnScreenConnect(const OutputPtr& output); + void OnScreenDisconnect(const OutputPtr& output); + void OnScreenChange(const OutputPtr& output); + + std::shared_ptr GetRSRenderComposer(ScreenId screenId); + void PostTask(const std::function& task); + void PostSyncTask(const std::function& task); + void PostDelayTask(const std::function& task, int64_t delayTime); + +private: + std::unordered_map> rsRenderComposerMap_; + std::shared_ptr handler_ = nullptr; + std::mutex mutex_; +}; +} // namespace OHOS +#endif // RS_RENDER_COMPOSER_THREAD_MANAGER_H \ No newline at end of file diff --git a/rosen/modules/render_service/composer/pipeline/src/rs_render_composer.cpp b/rosen/modules/render_service/composer/pipeline/src/rs_render_composer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4beb4894bae958cbb2739132c6a52214128d7661 --- /dev/null +++ b/rosen/modules/render_service/composer/pipeline/src/rs_render_composer.cpp @@ -0,0 +1,1046 @@ +/* + * Copyright (c) 2025-2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "rs_render_composer.h" + +#include +#include + +#include "frame_report.h" +#include "hdi_backend.h" +#include "hgm_frame_rate_manager.h" +#include "hisysevent.h" +#include "parameters.h" +#include "pipeline/hardware_thread/rs_realtime_refresh_rate_manager.h" +#include "rs_trace.h" +#include "vsync_sampler.h" + +#include "common/rs_exception_check.h" +#include "common/rs_optional_trace.h" +#include "common/rs_singleton.h" +#include "feature/hdr/rs_hdr_util.h" +#include "feature/round_corner_display/rs_round_corner_display_manager.h" +#include "pipeline/render_thread/rs_base_render_util.h" +#include "pipeline/main_thread/rs_main_thread.h" +#include "pipeline/render_thread/rs_uni_render_engine.h" +#include "pipeline/render_thread/rs_uni_render_thread.h" +#include "pipeline/render_thread/rs_uni_render_util.h" +#include "platform/common/rs_log.h" +#include "platform/common/rs_system_properties.h" +#include "platform/ohos/backend/rs_surface_ohos_gl.h" +#include "platform/ohos/backend/rs_surface_ohos_raster.h" +#include "screen_manager/rs_screen_manager.h" +#include "gfx/fps_info/rs_surface_fps_manager.h" +#include "gfx/first_frame_notifier/rs_first_frame_notifier.h" +#include "platform/common/rs_hisysevent.h" +#include "graphic_feature_param_manager.h" + +#ifdef RS_ENABLE_EGLIMAGE +#ifdef USE_M133_SKIA +#include "src/gpu/ganesh/gl/GrGLDefines.h" +#else +#include "src/gpu/gl/GrGLDefines.h" +#endif +#endif + +#ifdef RS_ENABLE_VK +#include "platform/ohos/backend/rs_surface_ohos_vulkan.h" +#include "feature/gpuComposition/rs_vk_image_manager.h" +#endif + +#ifdef RS_ENABLE_EGLIMAGE +#include "feature/gpuComposition/rs_egl_image_manager.h" +#endif // RS_ENABLE_EGLIMAGE + +#ifdef USE_VIDEO_PROCESSING_ENGINE +#include "metadata_helper.h" +#endif + +#ifdef RES_SCHED_ENABLE +#include "system_ability_definition.h" +#include "if_system_ability_manager.h" +#include +#include "ressched_event_listener.h" +#endif + +#ifdef RS_ENABLE_TV_PQ_METADATA +#include "feature/tv_metadata/rs_tv_metadata_manager.h" +#endif + +#undef LOG_TAG +#define LOG_TAG "RSHardwareThread" + +namespace OHOS { +namespace Rosen { +namespace { +constexpr uint32_t HARDWARE_THREAD_TASK_NUM = 2; +constexpr uint32_t HARD_JANK_TWO_TIME = 2; +constexpr int64_t REFRESH_PERIOD = 16667; // 16667us == 16.667ms +constexpr int64_t REPORT_LOAD_WARNING_INTERVAL_TIME = 5000000; // 5s == 5000000us +constexpr int64_t RESERVE_TIME = 1000000; // we reserve 1ms more for the composition +constexpr int64_t COMMIT_DELTA_TIME = 2; // 2ms +constexpr int64_t MAX_DELAY_TIME = 100; // 100ms +constexpr int64_t NS_MS_UNIT_CONVERSION = 1000000; +constexpr int64_t UNI_RENDER_VSYNC_OFFSET_DELAY_MODE = 3300000; // 3.3ms +constexpr uint32_t MAX_TOTAL_SURFACE_NAME_LENGTH = 320; +constexpr uint32_t MAX_SINGLE_SURFACE_NAME_LENGTH = 20; +// Threshold for abnormal time in the hardware pipeline +constexpr int HARDWARE_TIMEOUT = 800; +// The number of exceptions in the hardware pipeline required to achieve render_service reset +constexpr int HARDWARE_TIMEOUT_ABORT_CNT = 30; +// The number of exceptions in the hardware pipeline required to report hisysevent +constexpr int HARDWARE_TIMEOUT_CNT = 15; +const std::string PROCESS_NAME_FOR_HISYSEVENT = "/system/bin/render_service"; +const std::string HARDWARE_PIPELINE_TIMEOUT = "hardware_pipeline_timeout"; +} + +static int64_t SystemTime() +{ + timespec t = {}; + clock_gettime(CLOCK_MONOTONIC, &t); + return int64_t(t.tv_sec) * 1000000000LL + t.tv_nsec; // 1000000000ns == 1s +} + +RSRenderComposer::RSRenderComposer(const OutputPtr& output) +{ + init(output); +} + +void RSRenderComposer::init(const OutputPtr& output) +{ + if (output == nullptr) { + RS_LOGE("RSRenderComposer init output is nullptr"); + return; + } + hdiBackend_ = HdiBackend::GetInstance(); + hdiOutput_ = output; + screenId_ = hdiOutput_->GetScreenId(); + RS_LOGI("Start RSRendeComposerThread, screenId : %{public}" PRIu64, screenId_); + std::string threadName = "RSRendeComposerThread_" + std::to_string(screenId_); + runner_ = AppExecFwk::EventRunner::Create(threadName); + handler_ = std::make_shared(runner_); + + redrawCb_ = [this](const sptr& surface, const std::vector& layers, uint32_t screenId) { + return this->Redraw(surface, layers, screenId); + }; + rsRenderComposerContext_ = std::make_shared(); + + if (handler_) { + ScheduleTask( + [this]() { + // 需适配 +#if defined (RS_ENABLE_VK) + // Change vk interface type from UNIRENDER into UNPROTECTED_REDRAW, this is necessary for hardware init. + if (RSSystemProperties::IsUseVulkan()) { + RsVulkanContext::GetSingleton().SetIsProtected(false); + } +#endif +#ifdef RES_SCHED_ENABLE + // 需适配 + SubScribeSystemAbility(); +#endif + uniRenderEngine_ = std::make_shared(); + uniRenderEngine_->Init(); + + // 需适配 + // posttask for multithread safely release surface and image + ContextRegisterPostTask(); + threadTid_ = gettid(); + }).wait(); + } + auto onPrepareCompleteFunc = [this](auto& surface, const auto& param, void* data) { + OnPrepareComplete(surface, param, data); + }; + + if (hdiBackend_ != nullptr) { + hdiBackend_->RegPrepareComplete(onPrepareCompleteFunc, this); + } +} + +int32_t RSRenderComposer::GetHardwareThreadTid() const +{ + return threadTid_; +} + +uint32_t RSRenderComposer::GetUnExecuteTaskNum() +{ + return unExecuteTaskNum_.load(); +} + +void RSRenderComposer::IncUnExecuteTaskNum() +{ + unExecuteTaskNum_.fetch_add(1); +} + +void RSRenderComposer::SubUnExecuteTaskNum() +{ + unExecuteTaskNum_.fetch_sub(1); +} + +void RSRenderComposer::PrepareComposeFrame(RefreshRateParam& param, uint32_t& currentRate, + bool& hasGameScene, ScreenId& curScreenId, int64_t& delayTime) +{ + // 需适配 + // LayerComposeCollection::GetInstance().UpdateUniformOrOfflineComposeFrameNumberForDFX( + // rsRenderComposerContext_->GetLayersMap().size()); + + hgmHardwareUtils_.UpdateRefreshRateParam(); + param = hgmHardwareUtils_.GetRefreshRateParam(); + // 需适配 + auto& hgmCore = OHOS::Rosen::HgmCore::Instance(); + curScreenId = hgmCore.GetActiveScreenId(); + currentRate = hgmCore.GetScreenCurrentRefreshRate(curScreenId); + hasGameScene = FrameReport::GetInstance().HasGameScene(); +#ifdef RES_SCHED_ENABLE + ResschedEventListener::GetInstance()->ReportFrameToRSS(); +#endif + + // 需适配 + RSBaseRenderUtil::IncAcquiredBufferCount(); + IncUnExecuteTaskNum(); + RSMainThread::Instance()->SetHardwareTaskNum(GetUnExecuteTaskNum()); + + UpdateDelayTime(hgmCore, param, currentRate, hasGameScene); + delayTime = delayTime_; +} + +void RSRenderComposer::EndCheck(RSTimer timer) +{ + exceptionCheck_.pid_ = getpid(); + exceptionCheck_.uid_ = getuid(); + exceptionCheck_.processName_ = PROCESS_NAME_FOR_HISYSEVENT; + exceptionCheck_.exceptionPoint_ = HARDWARE_PIPELINE_TIMEOUT; + + if (timer.GetDuration() >= HARDWARE_TIMEOUT) { + if (++hardwareCount_ == HARDWARE_TIMEOUT_CNT) { + RS_LOGE("Hardware Thread Exception Count[%{public}d]", hardwareCount_); + exceptionCheck_.exceptionCnt_ = hardwareCount_; + exceptionCheck_.exceptionMoment_ = timer.GetSeconds(); + exceptionCheck_.UploadRenderExceptionData(); + } + } else { + hardwareCount_ = 0; + } + if (hardwareCount_ == HARDWARE_TIMEOUT_ABORT_CNT) { + exceptionCheck_.exceptionCnt_ = hardwareCount_; + exceptionCheck_.exceptionMoment_ = timer.GetSeconds(); + exceptionCheck_.UploadRenderExceptionData(); + sleep(1); // sleep 1s : abort will kill RS, sleep 1s for hisysevent report. + abort(); // The RS process needs to be restarted because 30 consecutive frames in hardware times out. + } +} + +int64_t RSRenderComposer::GetCurTimeCount() +{ + auto curTime = std::chrono::system_clock::now().time_since_epoch(); + return std::chrono::duration_cast(curTime).count(); +} + +std::string RSRenderComposer::GetSurfaceNameInLayers(const std::vector& layers) +{ + std::string surfaceName = "SurfaceName: ["; + bool isFirst = true; + for (const auto& layer : layers) { + if (layer == nullptr || layer->GetSurface() == nullptr) { + continue; + } + if (isFirst) { + surfaceName += layer->GetSurface()->GetName(); + isFirst = false; + continue; + } + surfaceName += ", " + layer->GetSurface()->GetName(); + } + surfaceName += "]"; + return surfaceName; +} + +std::string RSRenderComposer::GetSurfaceNameInLayersForTrace(const std::vector& layers) +{ + uint32_t count = layers.size(); + uint32_t max = 0; + for (const auto& layer : layers) { + if (layer == nullptr || layer->GetSurface() == nullptr) { + continue; + } + count += layer->GetSurface()->GetName().length(); + if (max < layer->GetZorder()) { + max = layer->GetZorder(); + } + } + bool exceedLimit = count > MAX_TOTAL_SURFACE_NAME_LENGTH; + std::string surfaceName = "Names:"; + for (const auto& layer : layers) { + if (layer == nullptr || layer->GetSurface() == nullptr) { + continue; + } + surfaceName += (exceedLimit ? layer->GetSurface()->GetName().substr(0, MAX_SINGLE_SURFACE_NAME_LENGTH) : + layer->GetSurface()->GetName()) + ","; + surfaceName.append("zorder: "); + surfaceName.append(std::to_string(layer->GetZorder())); + surfaceName.append(","); + if (layer->GetType() == GraphicLayerType::GRAPHIC_LAYER_TYPE_CURSOR && layer->GetZorder() < max) { + RS_LOGE("RSHardcursor is not on the top, hardcursor zorder:%{public}d", layer->GetZorder()); + } + } + + return surfaceName; +} + +void RSRenderComposer::ChangeLayersForActiveRectOutside(std::vector& layers, ScreenId screenId) +{ +#ifdef ROSEN_EMULATOR + RS_LOGD("emulator device do not need add layer"); + return; +#endif + if (!RSSystemProperties::IsSuperFoldDisplay() || layers.size() == 0) { + return; + } + + // 需适配 + auto screenManager = CreateOrGetScreenManager(); + if (!screenManager) { + return; + } + auto screenInfo = screenManager->QueryScreenInfo(screenId); + const RectI& reviseRect = screenInfo.reviseRect; + if (reviseRect.width_ <= 0 || reviseRect.height_ <= 0) { + return; + } + const RectI& maskRect = screenInfo.maskRect; + if (maskRect.width_ > 0 && maskRect.height_ > 0) { + auto solidColorLayer = HdiLayerInfo::CreateHdiLayerInfo(); + solidColorLayer->SetZorder(INT_MAX - 1); + solidColorLayer->SetTransform(GraphicTransformType::GRAPHIC_ROTATE_NONE); + GraphicIRect dstRect = {maskRect.left_, maskRect.top_, maskRect.width_, maskRect.height_}; + solidColorLayer->SetLayerSize(dstRect); + solidColorLayer->SetIsMaskLayer(true); + solidColorLayer->SetCompositionType(GraphicCompositionType::GRAPHIC_COMPOSITION_SOLID_COLOR); + bool debugFlag = (system::GetParameter("debug.foldscreen.shaft.color", "0") == "1"); + if (debugFlag) { + solidColorLayer->SetLayerColor({0, 255, 0, 255}); + } else { + solidColorLayer->SetLayerColor({0, 0, 0, 255}); + } + layers.emplace_back(solidColorLayer); + } + // 需适配 + using RSRcdManager = RSSingleton; + for (auto& layerInfo : layers) { + auto layerSurface = layerInfo->GetSurface(); + if (layerSurface != nullptr) { + auto rcdlayerInfo = RSRcdManager::GetInstance().GetLayerPair(layerSurface->GetName()); + if (rcdlayerInfo.second != RoundCornerDisplayManager::RCDLayerType::INVALID) { + continue; + } + } + GraphicIRect dstRect = layerInfo->GetLayerSize(); + GraphicIRect tmpRect = dstRect; + int reviseRight = reviseRect.left_ + reviseRect.width_; + int reviseBottom = reviseRect.top_ + reviseRect.height_; + tmpRect.x = std::clamp(dstRect.x, reviseRect.left_, reviseRight); + tmpRect.y = std::clamp(dstRect.y, reviseRect.top_, reviseBottom); + tmpRect.w = std::min(tmpRect.x + dstRect.w, reviseRight) - tmpRect.x; + tmpRect.h = std::min(tmpRect.y + dstRect.h, reviseBottom) - tmpRect.y; + layerInfo->SetLayerSize(tmpRect); + } +} + +void RSRenderComposer::AddRefreshRateCount(const OutputPtr& output) +{ + // 需适配 + auto screenManager = CreateOrGetScreenManager(); + if (screenManager == nullptr) { + RS_LOGE("AddRefreshRateCount screenManager is nullptr"); + return; + } + ScreenId id = screenManager->GetDefaultScreenId(); + auto& hgmCore = OHOS::Rosen::HgmCore::Instance(); + uint32_t currentRefreshRate = hgmCore.GetScreenCurrentRefreshRate(id); + auto [iter, success] = refreshRateCounts_.try_emplace(currentRefreshRate, 1); + if (!success) { + iter->second++; + } + if (output == nullptr) { + return; + } + RSRealtimeRefreshRateManager::Instance().CountRealtimeFrame(screenId_); + auto frameRateMgr = HgmCore::Instance().GetFrameRateMgr(); + if (frameRateMgr == nullptr) { + RS_LOGE("AddRefreshData fail, frameBufferSurfaceOhos_ is nullptr"); + return; + } + frameRateMgr->HandleRsFrame(); +} + +void RSRenderComposer::RecordTimestamp(const std::vector& layers) +{ + uint64_t currentTime = static_cast( + std::chrono::duration_cast( + std::chrono::steady_clock::now().time_since_epoch()).count()); + for (auto& layer : layers) { + if (layer == nullptr) { + continue; + } + uint64_t id = layer->GetNodeId(); + auto& surfaceFpsManager = RSSurfaceFpsManager::GetInstance(); + if (layer->GetBuffer() == nullptr) { + continue; + } + surfaceFpsManager.RecordPresentTime(id, currentTime, layer->GetBuffer()->GetSeqNum()); + } +} + +bool RSRenderComposer::IsDropDirtyFrame(const std::vector& layerInfos, uint32_t screenId) +{ +#ifdef ROSEN_EMULATOR + RS_LOGD("emulator device do not need drop dirty frame"); + return false; +#endif + if (!RSSystemProperties::IsSuperFoldDisplay()) { + return false; + } + // 需适配 + auto screenManager = CreateOrGetScreenManager(); + if (screenManager == nullptr) { + RS_LOGW("%{public}s: screenManager is null", __func__); + return false; + } + + auto rect = screenManager->QueryScreenInfo(screenId).activeRect; + if (rect.IsEmpty()) { + RS_LOGW("%{public}s: activeRect is empty", __func__); + return false; + } + GraphicIRect activeRect = {rect.left_, rect.top_, rect.width_, rect.height_}; + if (layerInfos.empty()) { + RS_LOGI("%{public}s: layerInfos is empty", __func__); + return false; + } + for (const auto& info : layerInfos) { + if (info == nullptr) { + continue; + } + auto layerSize = info->GetLayerSize(); + if (info->GetUniRenderFlag() && !(activeRect == layerSize)) { + RS_LOGI("%{publkic}s: Drop dirty frame cause activeRect:[%{public}d, %{public}d, %{public}d, %{public}d]" \ + "layerSize:[%{public}d, %{public}d, %{public}d, %{public}d]", __func__, activeRect.x, activeRect.y, + activeRect.w, activeRect.h, layerSize.x, layerSize.y, layerSize.w, layerSize.h); + return true; + } + } + return false; +} + +void RSRenderComposer::ProcessComposeFrame(RefreshRateParam param, uint32_t currentRate, + bool hasGameScene, ScreenId curScreenId) +{ + std::string threadName = "Hardware_" + std::to_string(screenId_); + RSTimer rsTimer(threadName.c_str(), HARDWARE_TIMEOUT); + + auto layers = rsRenderComposerContext_->GetLayersVec(); +#ifdef HIPERF_TRACE_ENABLE + RS_LOGW("hiperf_surface_counter3 %{public}" PRIu64 " ", static_cast(layers.size())); +#endif + int64_t startTime = GetCurTimeCount(); + std::string surfaceName = GetSurfaceNameInLayers(layers); + RS_LOGD("CommitAndReleaseLayers task execute, %{public}s", surfaceName.c_str()); + if (hdiOutput_ == nullptr || hdiBackend_ == nullptr) { + RS_LOGI("CommitAndReleaseLayers task return, %{public}s", surfaceName.c_str()); + return; + } + int64_t startTimeNs = 0; + int64_t endTimeNs = 0; + + // 需适配 + RSFirstFrameNotifier::GetInstance().ExecIfFirstFrameCommit(screenId_); + + RS_LOGI_IF(DEBUG_COMPOSER, "CommitAndReleaseData hasGameScene is %{public}d %{public}s", + hasGameScene, surfaceName.c_str()); + if (hasGameScene) { + startTimeNs = std::chrono::duration_cast( + std::chrono::steady_clock::now().time_since_epoch()).count(); + } + RS_TRACE_NAME_FMT("CommitLayers rate:%u,now:%" PRIu64 ",vsyncId:%" PRIu64 ",size:%zu,%s", + currentRate, param.frameTimestamp, param.vsyncId, layers.size(), + GetSurfaceNameInLayersForTrace(layers).c_str()); + RS_LOGD("CommitLayers rate:%{public}u, now:%{public}" PRIu64 ",vsyncId:%{public}" PRIu64 ", \ + size:%{public}zu, %{public}s", currentRate, param.frameTimestamp, param.vsyncId, layers.size(), + GetSurfaceNameInLayersForTrace(layers).c_str()); + + // 需适配 + bool isScreenPoweringOff = false; + auto screenManager = CreateOrGetScreenManager(); + if (screenManager) { + isScreenPoweringOff = RSSystemProperties::IsSmallFoldDevice() && + screenManager->IsScreenPoweringOff(screenId_); + } + + bool shouldDropFrame = isScreenPoweringOff || IsDropDirtyFrame(layers, screenId_); + if (!shouldDropFrame) { + hgmHardwareUtils_.ExecuteSwitchRefreshRate(hdiOutput_, param.rate); + hgmHardwareUtils_.PerformSetActiveMode( + hdiOutput_, param.frameTimestamp, param.constraintRelativeTime); + AddRefreshRateCount(hdiOutput_); + } + + if (RSSystemProperties::IsSuperFoldDisplay() && screenId_ == 0) { + std::vector reviseLayers = layers; + ChangeLayersForActiveRectOutside(reviseLayers, curScreenId); + hdiOutput_->SetLayerInfo(reviseLayers); + } else { + hdiOutput_->SetLayerInfo(layers); + } + bool doRepaint = hdiOutput_->IsDeviceValid() && !shouldDropFrame; + if (doRepaint) { + hdiBackend_->Repaint(hdiOutput_); + RecordTimestamp(layers); + } + hdiOutput_->ReleaseLayers(releaseFence_); + // 需适配 + RSBaseRenderUtil::DecAcquiredBufferCount(); + RSUniRenderThread::Instance().NotifyScreenNodeBufferReleased(); + if (hasGameScene) { + endTimeNs = std::chrono::duration_cast( + std::chrono::steady_clock::now().time_since_epoch()).count(); + FrameReport::GetInstance().SetLastSwapBufferTime(endTimeNs - startTimeNs); + } + + SubUnExecuteTaskNum(); + RS_LOGD_IF(DEBUG_COMPOSER, "CommitAndReleaseData unExecuteTaskNum_:%{public}d," + " HARDWARE_THREAD_TASK_NUM:%{public}d, %{public}s", + GetUnExecuteTaskNum(), HARDWARE_THREAD_TASK_NUM, surfaceName.c_str()); + // 需适配 + if (GetUnExecuteTaskNum() <= HARDWARE_THREAD_TASK_NUM) { + RSMainThread::Instance()->NotifyHardwareThreadCanExecuteTask(); + } + RSMainThread::Instance()->SetTaskEndWithTime(SystemTime() - lastActualTime_); + lastActualTime_ = param.actualTimestamp; + int64_t endTime = GetCurTimeCount(); + uint64_t frameTime = endTime - startTime; + uint32_t missedFrames = frameTime / REFRESH_PERIOD; + uint16_t frameRate = currentRate; + if (missedFrames >= HARD_JANK_TWO_TIME && + endTime - intervalTimePoints_ > REPORT_LOAD_WARNING_INTERVAL_TIME) { + RS_LOGI("CommitAndReleaseLayers report load event frameTime: %{public}" PRIu64 + " missedFrame: %{public}" PRIu32 " frameRate:%{public}" PRIu16 " %{public}s", + frameTime, missedFrames, frameRate, surfaceName.c_str()); + intervalTimePoints_ = endTime; + RS_TRACE_NAME("RSHardwareThread::CommitAndReleaseLayers HiSysEventWrite in RSHardwareThread"); + RSHiSysEvent::EventWrite(RSEventName::RS_HARDWARE_THREAD_LOAD_WARNING, RSEventType::RS_STATISTIC, + "FRAME_RATE", frameRate, "MISSED_FRAMES", missedFrames, "FRAME_TIME", frameTime); + } + + EndCheck(rsTimer); +} + +void RSRenderComposer::UpdateLayersAndComposerFrame() +{ + RefreshRateParam param; + uint32_t currentRate = 0; + bool hasGameScene = false; + ScreenId curScreenId = 0; + int64_t delayTime = 0; + PrepareComposeFrame(param, currentRate, hasGameScene, curScreenId, delayTime); + + std::function task = [this, param = param, currentRate = currentRate, + hasGameScene = hasGameScene, curScreenId = curScreenId]() { + // switch () + // { + // case : + // AddComposerLayer(); + // break; + // case : + // UpdateComposerLayer(); + // break; + // case : + // DeleteComposerLayer(); + // break; + // default: + // return; + // } + ProcessComposeFrame(param, currentRate, hasGameScene, curScreenId); + }; + PostDelayTask(task, delayTime); +} + +void RSRenderComposer::CalculateDelayTime(OHOS::Rosen::HgmCore& hgmCore, RefreshRateParam param, uint32_t currentRate, + int64_t currTime) +{ + int64_t frameOffset = 0; + int64_t vsyncOffset = 0; + int64_t idealPipelineOffset = 0; + int64_t pipelineOffset = 0; + int64_t expectCommitTime = 0; + int64_t periodNum = 0; + int64_t idealPeriod = hgmCore.GetIdealPeriod(currentRate); + int64_t period = CreateVSyncSampler()->GetHardwarePeriod(); + uint64_t dvsyncOffset = RSMainThread::Instance()->GetRealTimeOffsetOfDvsync(param.frameTimestamp); + int64_t compositionTime = period; + + if (!hgmCore.GetLtpoEnabled()) { + vsyncOffset = UNI_RENDER_VSYNC_OFFSET_DELAY_MODE; + // 2 period for draw and composition, pipelineOffset = 2 * period + frameOffset = 2 * period + vsyncOffset - static_cast(param.fastComposeTimeStampDiff); + } else { + idealPipelineOffset = hgmCore.GetIdealPipelineOffset(); + pipelineOffset = hgmCore.GetPipelineOffset(); + vsyncOffset = CreateVSyncGenerator()->GetVSyncOffset(); + periodNum = idealPeriod == 0 ? 0 : idealPipelineOffset / idealPeriod; + + if (vsyncOffset >= period) { + vsyncOffset = 0; + } + if (periodNum * idealPeriod + vsyncOffset + IDEAL_PULSE < idealPipelineOffset) { + periodNum = periodNum + 1; + } + frameOffset = periodNum * idealPeriod + vsyncOffset + + static_cast(dvsyncOffset) - static_cast(param.fastComposeTimeStampDiff); + } + expectCommitTime = param.actualTimestamp + frameOffset - compositionTime - RESERVE_TIME; + int64_t diffTime = expectCommitTime - currTime; + if (diffTime > 0 && period > 0) { + delayTime_ = std::round(diffTime * 1.0f / NS_MS_UNIT_CONVERSION); + } + RS_TRACE_NAME_FMT("CalculateDelayTime pipelineOffset: %" PRId64 ", actualTimestamp: %" PRId64 ", " \ + "expectCommitTime: %" PRId64 ", currTime: %" PRId64 ", diffTime: %" PRId64 ", delayTime: %" PRId64 ", " \ + "frameOffset: %" PRId64 ", dvsyncOffset: %" PRIu64 ", vsyncOffset: %" PRId64 ", idealPeriod: %" PRId64 ", " \ + "period: %" PRId64 ", idealPipelineOffset: %" PRId64 ", fastComposeTimeStampDiff: %" PRIu64 "", + pipelineOffset, param.actualTimestamp, expectCommitTime, currTime, diffTime, delayTime_, + frameOffset, dvsyncOffset, vsyncOffset, idealPeriod, period, + idealPipelineOffset, param.fastComposeTimeStampDiff); + RS_LOGD_IF(DEBUG_PIPELINE, "CalculateDelayTime period:%{public}" PRId64 " delayTime:%{public}" PRId64 "", period, + delayTime_); +} + +int32_t RSRenderComposer::AdaptiveModeStatus(const OutputPtr& output) +{ + if (hdiBackend_ == nullptr) { + RS_LOGE("AdaptiveModeStatus hdiBackend_ is nullptr"); + return SupportASStatus::NOT_SUPPORT; + } + + // 需适配 + auto& hgmCore = OHOS::Rosen::HgmCore::Instance(); + + // if in game adaptive vsync mode and do direct composition,send layer immediately + auto frameRateMgr = hgmCore.GetFrameRateMgr(); + if (frameRateMgr != nullptr) { + int32_t adaptiveStatus = frameRateMgr->AdaptiveStatus(); + RS_LOGD("CommitAndReleaseLayers send layer adaptiveStatus: %{public}u", adaptiveStatus); + if (adaptiveStatus == SupportASStatus::SUPPORT_AS) { + return SupportASStatus::SUPPORT_AS; + } + if (adaptiveStatus == SupportASStatus::GAME_SCENE_SKIP) { + return SupportASStatus::GAME_SCENE_SKIP; + } + } + return SupportASStatus::NOT_SUPPORT; +} + +bool RSRenderComposer::IsDelayRequired(OHOS::Rosen::HgmCore& hgmCore, RefreshRateParam param, + const OutputPtr& output, bool hasGameScene) +{ + if (param.isForceRefresh) { + RS_LOGD("CommitAndReleaseLayers in Force Refresh"); + RS_TRACE_NAME("CommitAndReleaseLayers in Force Refresh"); + return false; + } + + if (hgmCore.GetLtpoEnabled()) { + if (AdaptiveModeStatus(output) == SupportASStatus::SUPPORT_AS) { + RS_LOGD("CommitAndReleaseLayers in Adaptive Mode"); + RS_TRACE_NAME("CommitAndReleaseLayers in Adaptive Mode"); + return false; + } + if (hasGameScene && AdaptiveModeStatus(output) == SupportASStatus::GAME_SCENE_SKIP) { + RS_LOGD("CommitAndReleaseLayers skip delayTime Calculation"); + RS_TRACE_NAME("CommitAndReleaseLayers in Game Scene and skiped delayTime Calculation"); + return false; + } + } else { + if (!hgmCore.IsDelayMode()) { + return false; + } + if (hasGameScene) { + RS_LOGD("CommitAndReleaseLayers in Game Scene"); + RS_TRACE_NAME("CommitAndReleaseLayers in Game Scene"); + return false; + } + } + return true; +} + +void RSRenderComposer::UpdateDelayTime(OHOS::Rosen::HgmCore& hgmCore, RefreshRateParam param, + uint32_t currentRate, bool hasGameScene) +{ + delayTime_ = 0; + RS_LOGI_IF(DEBUG_COMPOSER, "CommitAndReleaseData hgmCore's LtpoEnabled is %{public}d", hgmCore.GetLtpoEnabled()); + int64_t currTime = SystemTime(); + if (IsDelayRequired(hgmCore, param, hdiOutput_, hasGameScene)) { + CalculateDelayTime(hgmCore, param, currentRate, currTime); + } + + // We need to ensure the order of composition frames, postTaskTime(n + 1) must > postTaskTime(n), + // and we give a delta time more between two composition tasks. + int64_t currCommitTime = currTime + delayTime_ * NS_MS_UNIT_CONVERSION; + if (currCommitTime <= lastCommitTime_) { + delayTime_ = delayTime_ + + std::round((lastCommitTime_ - currCommitTime) * 1.0f / NS_MS_UNIT_CONVERSION) + + COMMIT_DELTA_TIME; + RS_LOGD("CommitAndReleaseLayers vsyncId: %{public}" PRIu64 ", " \ + "update delayTime: %{public}" PRId64 ", currCommitTime: %{public}" PRId64 ", " \ + "lastCommitTime: %{public}" PRId64, param.vsyncId, delayTime_, currCommitTime, lastCommitTime_); + RS_TRACE_NAME_FMT("update delayTime: %" PRId64 ", currCommitTime: %" PRId64 ", lastCommitTime: %" PRId64 "", + delayTime_, currCommitTime, lastCommitTime_); + } + if (delayTime_ < 0 || delayTime_ >= MAX_DELAY_TIME) { + delayTime_ = 0; + } + lastCommitTime_ = currTime + delayTime_ * NS_MS_UNIT_CONVERSION; +} + +#ifdef USE_VIDEO_PROCESSING_ENGINE +GraphicColorGamut RSRenderComposer::ComputeTargetColorGamut(const std::vector& layers) +{ + using namespace HDI::Display::Graphic::Common::V1_0; + GraphicColorGamut colorGamut = GRAPHIC_COLOR_GAMUT_SRGB; + for (auto& layer : layers) { + if (layer == nullptr) { + RS_LOGE("ComputeTargetColorGamut layer is nullptr"); + continue; + } + auto buffer = layer->GetBuffer(); + if (buffer == nullptr) { + RS_LOGW("ComputeTargetColorGamut The buffer of layer is nullptr"); + continue; + } + + CM_ColorSpaceInfo colorSpaceInfo; + if (MetadataHelper::GetColorSpaceInfo(buffer, colorSpaceInfo) != GSERROR_OK) { + RS_LOGD("ComputeTargetColorGamut Get color space failed"); + continue; + } + + if (colorSpaceInfo.primaries != COLORPRIMARIES_SRGB) { + RS_LOGD("ComputeTargetColorData fail, primaries is %{public}d", + colorSpaceInfo.primaries); + colorGamut = GRAPHIC_COLOR_GAMUT_DISPLAY_P3; + break; + } + } + + return colorGamut; +} + +GraphicPixelFormat RSRenderComposer::ComputeTargetPixelFormat(const std::vector& layers) +{ + using namespace HDI::Display::Graphic::Common::V1_0; + GraphicPixelFormat pixelFormat = GRAPHIC_PIXEL_FMT_RGBA_8888; + for (auto& layer : layers) { + if (layer == nullptr) { + continue; + } + auto buffer = layer->GetBuffer(); + if (buffer == nullptr) { + RS_LOGW("ComputeTargetPixelFormat The buffer of layer is nullptr"); + continue; + } + + auto bufferPixelFormat = buffer->GetFormat(); + if (bufferPixelFormat == GRAPHIC_PIXEL_FMT_RGBA_1010108) { + pixelFormat = GRAPHIC_PIXEL_FMT_RGBA_1010102; + if (RSHdrUtil::GetRGBA1010108Enabled()) { + pixelFormat = GRAPHIC_PIXEL_FMT_RGBA_1010108; + RS_LOGD("ComputeTargetPixelFormat pixelformat is set to GRAPHIC_PIXEL_FMT_RGBA_1010108"); + } + break; + } + if (bufferPixelFormat == GRAPHIC_PIXEL_FMT_RGBA_1010102 || + bufferPixelFormat == GRAPHIC_PIXEL_FMT_YCBCR_P010 || + bufferPixelFormat == GRAPHIC_PIXEL_FMT_YCRCB_P010) { + pixelFormat = GRAPHIC_PIXEL_FMT_RGBA_1010102; + RS_LOGD("ComputeTargetPixelFormat pixelformat is set to 1010102 for 10bit buffer"); + } + } + + return pixelFormat; +} + +bool RSRenderComposer::ConvertColorGamutToSpaceType(const GraphicColorGamut& colorGamut, + HDI::Display::Graphic::Common::V1_0::CM_ColorSpaceType& colorSpaceType) +{ + using namespace HDI::Display::Graphic::Common::V1_0; + static const std::map RS_TO_COMMON_COLOR_SPACE_TYPE_MAP { + {GRAPHIC_COLOR_GAMUT_STANDARD_BT601, CM_BT601_EBU_FULL}, + {GRAPHIC_COLOR_GAMUT_STANDARD_BT709, CM_BT709_FULL}, + {GRAPHIC_COLOR_GAMUT_SRGB, CM_SRGB_FULL}, + {GRAPHIC_COLOR_GAMUT_ADOBE_RGB, CM_ADOBERGB_FULL}, + {GRAPHIC_COLOR_GAMUT_DISPLAY_P3, CM_P3_FULL}, + {GRAPHIC_COLOR_GAMUT_BT2020, CM_DISPLAY_BT2020_SRGB}, + {GRAPHIC_COLOR_GAMUT_BT2100_PQ, CM_BT2020_PQ_FULL}, + {GRAPHIC_COLOR_GAMUT_BT2100_HLG, CM_BT2020_HLG_FULL}, + {GRAPHIC_COLOR_GAMUT_DISPLAY_BT2020, CM_DISPLAY_BT2020_SRGB}, + }; + + if (RS_TO_COMMON_COLOR_SPACE_TYPE_MAP.find(colorGamut) == RS_TO_COMMON_COLOR_SPACE_TYPE_MAP.end()) { + return false; + } + + colorSpaceType = RS_TO_COMMON_COLOR_SPACE_TYPE_MAP.at(colorGamut); + return true; +} +#endif + +void RSRenderComposer::RedrawScreenRCD(RSPaintFilterCanvas& canvas, const std::vector& layers) +{ + RS_TRACE_NAME("RSHardwareThread::RedrawScreenRCD, threadId: " + std::to_string(screenId_)); + using RSRcdManager = RSSingleton; + std::vector> rcdLayerInfoList; + for (const auto& layer : layers) { + if (layer == nullptr) { + continue; + } + if (layer->GetCompositionType() == GraphicCompositionType::GRAPHIC_COMPOSITION_DEVICE || + layer->GetCompositionType() == GraphicCompositionType::GRAPHIC_COMPOSITION_DEVICE_CLEAR || + layer->GetCompositionType() == GraphicCompositionType::GRAPHIC_COMPOSITION_SOLID_COLOR) { + continue; + } + auto layerSurface = layer->GetSurface(); + if (layerSurface != nullptr) { + auto rcdlayerInfo = RSRcdManager::GetInstance().GetLayerPair(layerSurface->GetName()); + if (rcdlayerInfo.second != RoundCornerDisplayManager::RCDLayerType::INVALID) { + rcdLayerInfoList.push_back(rcdlayerInfo); + continue; + } + } else { + RS_LOGE("RedrawScreenRCD layerSurface is nullptr"); + continue; + } + } + + if (RSRcdManager::GetInstance().GetRcdEnable()) { + RSRcdManager::GetInstance().DrawRoundCorner(rcdLayerInfoList, &canvas); + } +} + +std::shared_ptr RSRenderComposer::CreateFrameBufferSurfaceOhos(const sptr& surface) +{ + std::shared_ptr rsSurface = nullptr; +#if (defined RS_ENABLE_GL) && (defined RS_ENABLE_EGLIMAGE) + if (RSSystemProperties::GetGpuApiType() == GpuApiType::OPENGL) { + rsSurface = std::make_shared(surface); + } +#endif +#if (defined RS_ENABLE_VK) + if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN || + RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) { + rsSurface = std::make_shared(surface); + } +#endif + RS_LOGD("Redraw: CreateFrameBufferSurfaceOhos."); + return rsSurface; +} + +void RSRenderComposer::Redraw(const sptr& surface, const std::vector& layers, + uint32_t screenId) +{ + RS_TRACE_NAME("RSHardwareThread::Redraw, threadId: " + std::to_string(screenId_)); + // 需适配 + std::unique_lock lock(preAllocMutex_, std::try_to_lock); + auto screenManager = CreateOrGetScreenManager(); + if (screenManager == nullptr) { + RS_LOGE("Redraw: screenManager is null."); + return; + } + if (surface == nullptr || uniRenderEngine_ == nullptr) { + RS_LOGE("Redraw: surface or uniRenderEngine is null."); + return; + } + bool isProtected = false; + + static bool isCCMDrmEnabled = DRMParam::IsDrmEnable(); + bool isDrmEnabled = RSSystemProperties::GetDrmEnabled() && isCCMDrmEnabled; + +#ifdef RS_ENABLE_VK + if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN || + RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) { + if (isDrmEnabled) { + for (const auto& layer : layers) { + if (layer && layer->GetBuffer() && (layer->GetBuffer()->GetUsage() & BUFFER_USAGE_PROTECTED)) { + isProtected = true; + break; + } + } + if (RSSystemProperties::IsUseVulkan()) { + RsVulkanContext::GetSingleton().SetIsProtected(isProtected); + } + } else { + RsVulkanContext::GetSingleton().SetIsProtected(false); + } + } +#endif + + RS_LOGD("RsDebug Redraw flush frame buffer start"); + bool forceCPU = RSBaseRenderEngine::NeedForceCPU(layers); + auto screenInfo = screenManager->QueryScreenInfo(screenId); + std::shared_ptr drawingColorSpace = nullptr; +#ifdef USE_VIDEO_PROCESSING_ENGINE + GraphicColorGamut colorGamut = ComputeTargetColorGamut(layers); + GraphicPixelFormat pixelFormat = ComputeTargetPixelFormat(layers); + RS_LOGD("Redraw computed target color gamut: %{public}d," + "pixel format: %{public}d, frame width: %{public}d, frame height: %{public}d", + colorGamut, pixelFormat, screenInfo.phyWidth, screenInfo.phyHeight); + auto renderFrameConfig = RSBaseRenderUtil::GetFrameBufferRequestConfig(screenInfo, + isProtected, colorGamut, pixelFormat); + drawingColorSpace = RSBaseRenderEngine::ConvertColorGamutToDrawingColorSpace(colorGamut); + // set color space to surface buffer metadata + using namespace HDI::Display::Graphic::Common::V1_0; + CM_ColorSpaceType colorSpace = CM_SRGB_FULL; + if (ConvertColorGamutToSpaceType(colorGamut, colorSpace)) { + if (surface->SetUserData("ATTRKEY_COLORSPACE_INFO", std::to_string(colorSpace)) != GSERROR_OK) { + RS_LOGD("Redraw set user data failed"); + } + } +#else + auto renderFrameConfig = RSBaseRenderUtil::GetFrameBufferRequestConfig(screenInfo, isProtected); +#endif + // override redraw frame buffer with physical screen resolution. + renderFrameConfig.width = static_cast(screenInfo.phyWidth); + renderFrameConfig.height = static_cast(screenInfo.phyHeight); + + std::shared_ptr frameBufferSurfaceOhos; + auto surfaceId = surface->GetUniqueId(); + { + std::lock_guard lock(frameBufferSurfaceOhosMapMutex_); + if (frameBufferSurfaceOhosMap_.count(surfaceId)) { + frameBufferSurfaceOhos = frameBufferSurfaceOhosMap_[surfaceId]; + } else { + frameBufferSurfaceOhos = CreateFrameBufferSurfaceOhos(surface); + frameBufferSurfaceOhosMap_[surfaceId] = frameBufferSurfaceOhos; + } + } + FrameContextConfig frameContextConfig = {isProtected, false}; +#ifdef RS_ENABLE_VKQUEUE_PRIORITY + frameContextConfig.independentContext = RSSystemProperties::GetVkQueuePriorityEnable(); +#endif + std::lock_guard ohosSurfaceLock(surfaceMutex_); + auto renderFrame = uniRenderEngine_->RequestFrame(frameBufferSurfaceOhos, renderFrameConfig, + forceCPU, true, frameContextConfig); + if (renderFrame == nullptr) { + RS_LOGE("RsDebug Redraw failed to request frame."); + return; + } + auto canvas = renderFrame->GetCanvas(); + if (canvas == nullptr) { + RS_LOGE("RsDebug Redraw canvas is nullptr."); + return; + } +#ifdef RS_ENABLE_VK + if (RSSystemProperties::IsUseVulkan()) { + canvas->Clear(Drawing::Color::COLOR_TRANSPARENT); + } +#endif + +#ifdef USE_VIDEO_PROCESSING_ENGINE + uniRenderEngine_->DrawLayers(*canvas, layers, false, screenInfo, colorGamut); +#else + uniRenderEngine_->DrawLayers(*canvas, layers, false, screenInfo); +#endif + RedrawScreenRCD(*canvas, layers); +#ifdef RS_ENABLE_TV_PQ_METADATA + auto rsSurface = renderFrame->GetSurface(); + RSTvMetadataManager::Instance().CopyFromLayersToSurface(layers, rsSurface); +#endif + renderFrame->Flush(); + RS_LOGD("RsDebug Redraw flush frame buffer end"); +} + +void RSRenderComposer::OnPrepareComplete(sptr& surface, const PrepareCompleteParam& param, void* data) +{ + // unused data. + (void)(data); + + if (!param.needFlushFramebuffer) { + return; + } + + if (redrawCb_ != nullptr) { + redrawCb_(surface, param.layers, param.screenId); + } +} + +void RSRenderComposer::PostTask(const std::function& task) +{ + if (handler_) { + handler_->PostTask(task, AppExecFwk::EventQueue::Priority::IMMEDIATE); + } +} + +void RSRenderComposer::PostSyncTask(const std::function& task) +{ + if (handler_) { + handler_->PostSyncTask(task, AppExecFwk::EventQueue::Priority::IMMEDIATE); + } +} + +void RSRenderComposer::PostDelayTask(const std::function& task, int64_t delayTime) +{ + if (handler_) { + handler_->PostTask(task, delayTime, AppExecFwk::EventQueue::Priority::IMMEDIATE); + } +} + +void RSRenderComposer::SubScribeSystemAbility() +{ + RS_LOGI("%{public}s", __func__); + // 需适配 + sptr systemAbilityManager = + SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (!systemAbilityManager) { + RS_LOGE("%{public}s failed to get system ability manager client", __func__); + return; + } + std::string threadName = "RSHardwareThread"; + std::string strUid = std::to_string(getuid()); + std::string strPid = std::to_string(getpid()); + std::string strTid = std::to_string(gettid()); + + saStatusChangeListener_ = new (std::nothrow)VSyncSystemAbilityListener(threadName, strUid, strPid, strTid); + int32_t ret = systemAbilityManager->SubscribeSystemAbility(RES_SCHED_SYS_ABILITY_ID, saStatusChangeListener_); + if (ret != ERR_OK) { + RS_LOGE("%{public}s subscribe system ability %{public}d failed.", __func__, RES_SCHED_SYS_ABILITY_ID); + saStatusChangeListener_ = nullptr; + } +} + +void RSRenderComposer::ContextRegisterPostTask() +{ + // 需适配 +#if defined(RS_ENABLE_VK) && defined(IS_ENABLE_DRM) + if (RSSystemProperties::IsUseVulkan()) { + RsVulkanContext::GetSingleton().SetIsProtected(true); + auto context = RsVulkanContext::GetSingleton().GetDrawingContext(); + if (context) { + context->RegisterPostFunc([this](const std::function& task) { PostTask(task); }); + } + RsVulkanContext::GetSingleton().SetIsProtected(false); + if (context) { + context->RegisterPostFunc([this](const std::function& task) { PostTask(task); }); + } + } +#endif +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/rosen/modules/render_service/composer/pipeline/src/rs_render_composer_agent.cpp b/rosen/modules/render_service/composer/pipeline/src/rs_render_composer_agent.cpp new file mode 100644 index 0000000000000000000000000000000000000000..56e03b1f329435bbf3b2e1ca518094177c90928e --- /dev/null +++ b/rosen/modules/render_service/composer/pipeline/src/rs_render_composer_agent.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2025-2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "rs_render_composer_agent.h" +#include "platform/common/rs_log.h" +#include "rs_trace.h" + +namespace OHOS { +namespace Rosen { +RSRenderComposerAgent::RSRenderComposerAgent(std::shared_ptr rsRenderComposer) : + rsRenderComposer_(rsRenderComposer) {} + +void RSRenderComposerAgent::UpdateLayersAndComposerFrame() +{ + rsRenderComposer_->UpdateLayersAndComposerFrame(); +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/rosen/modules/render_service/composer/pipeline/src/rs_render_composer_context.cpp b/rosen/modules/render_service/composer/pipeline/src/rs_render_composer_context.cpp new file mode 100644 index 0000000000000000000000000000000000000000..01a296967b32dae61433eaaf703b6d4b2c103bcf --- /dev/null +++ b/rosen/modules/render_service/composer/pipeline/src/rs_render_composer_context.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2025-2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "rs_render_composer_context.h" + +namespace OHOS { +namespace Rosen { +void RSRenderComposerContext::AddComposerLayer() +{ + +} + +void RSRenderComposerContext::UpdateComposerLayer() +{ + +} + +void RSRenderComposerContext::DeleteComposerLayer() +{ + +} + +// std::unordered_map>& RSRenderComposerContext::GetLayersMap() +// { +// return layersMap_; +// } + +std::vector& RSRenderComposerContext::GetLayersVec() +{ + return layersVec_; +} +} // namespace Rosen +} // namespace OHOSl \ No newline at end of file diff --git a/rosen/modules/render_service/composer/pipeline/src/rs_render_composer_manager.cpp b/rosen/modules/render_service/composer/pipeline/src/rs_render_composer_manager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..65172865fca95f16058c93f54b9ed339993ff81e --- /dev/null +++ b/rosen/modules/render_service/composer/pipeline/src/rs_render_composer_manager.cpp @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2025-2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "rs_render_composer_manager.h" +#include "platform/common/rs_log.h" +#include "rs_trace.h" + +namespace OHOS { +namespace Rosen { +RSRenderComposerManager::RSRenderComposerManager(std::shared_ptr& handler) : + handler_(handler) +{ + RS_LOGI("Create RSRenderComposerManager"); +} + +void RSRenderComposerManager::OnScreenConnect(const OutputPtr& output) +{ + if (output == nullptr) { + return; + } + RS_LOGI("OnScreenConnect screenId: %{public}u", output->GetScreenId()); + std::function task = [this, output = output]() { + auto renderComposer = std::make_shared(output); + rsRenderComposerMap_.insert(std::pair(output->GetScreenId(), renderComposer)); + }; + PostTask(task); +} + +void RSRenderComposerManager::OnScreenDisconnect(const OutputPtr& output) +{ + if (output == nullptr) { + return; + } + RS_LOGI("OnScreenDisconnect screenId: %{public}u", output->GetScreenId()); + std::function task = [this, output = output]() { + rsRenderComposerMap_.erase(output->GetScreenId()); + }; + PostTask(task); +} + +void RSRenderComposerManager::OnScreenChange(const OutputPtr& output) +{ + (void)output; +} + +std::shared_ptr RSRenderComposerManager::GetRSRenderComposer(ScreenId screenId) +{ + std::shared_ptr rsRenderComposer = nullptr; + std::function task = [this, screenId = screenId, &rsRenderComposer]() { + auto iter = rsRenderComposerMap_.find(screenId); + if (iter == rsRenderComposerMap_.end()) { + RS_LOGE("Not find screenId: %{public}" PRIu64, screenId); + rsRenderComposer = nullptr; + return; + } + rsRenderComposer = iter->second; + }; + PostSyncTask(task); + return rsRenderComposer; +} + +void RSRenderComposerManager::PostTask(const std::function& task) +{ + if (handler_) { + handler_->PostTask(task, AppExecFwk::EventQueue::Priority::IMMEDIATE); + } +} + +void RSRenderComposerManager::PostSyncTask(const std::function& task) +{ + if (handler_) { + handler_->PostSyncTask(task, AppExecFwk::EventQueue::Priority::IMMEDIATE); + } +} + +void RSRenderComposerManager::PostDelayTask(const std::function& task, int64_t delayTime) +{ + if (handler_) { + handler_->PostTask(task, delayTime, AppExecFwk::EventQueue::Priority::IMMEDIATE); + } +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/rosen/modules/render_service/core/pipeline/hardware_thread/rs_realtime_refresh_rate_manager.h b/rosen/modules/render_service/core/pipeline/hardware_thread/rs_realtime_refresh_rate_manager.h index e439c377965ef75689cc5506114876d7d7a363c8..d491e864316931f2a1dcc0492f323b7a1f96a15e 100644 --- a/rosen/modules/render_service/core/pipeline/hardware_thread/rs_realtime_refresh_rate_manager.h +++ b/rosen/modules/render_service/core/pipeline/hardware_thread/rs_realtime_refresh_rate_manager.h @@ -46,6 +46,7 @@ public: uint32_t GetRealtimeRefreshRate(ScreenId screenId); private: friend class RSHardwareThread; + friend class RSRenderComposer; RSRealtimeRefreshRateManager() = default; ~RSRealtimeRefreshRateManager() = default;