1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "pipeline/rs_pointer_window_manager.h"
17 #include "feature/hwc/rs_uni_hwc_compute_util.h"
18 #include "common/rs_optional_trace.h"
19 #include "feature_cfg/graphic_feature_param_manager.h"
20 #include "pipeline/main_thread/rs_main_thread.h"
21 #ifdef RS_ENABLE_GPU
22 #include "pipeline/render_thread/rs_uni_render_util.h"
23 #include "screen_manager/screen_types.h"
24 #endif
25 namespace OHOS {
26 namespace Rosen {
27 namespace {
28 constexpr int MIN_LAYER_WIDTH = 2;
29 constexpr int MIN_LAYER_HEIGHT = 2;
30 }
Instance()31 RSPointerWindowManager& RSPointerWindowManager::Instance()
32 {
33 static RSPointerWindowManager instance;
34 return instance;
35 }
36
RSPointerWindowManager()37 RSPointerWindowManager::RSPointerWindowManager()
38 {
39 isHardCursorEnable_ = RSPointerWindowManager::GetHardCursorEnabledPass();
40 }
41
UpdatePointerDirtyToGlobalDirty(std::shared_ptr<RSSurfaceRenderNode> & pointWindow,std::shared_ptr<RSScreenRenderNode> & curScreenNode)42 void RSPointerWindowManager::UpdatePointerDirtyToGlobalDirty(std::shared_ptr<RSSurfaceRenderNode>& pointWindow,
43 std::shared_ptr<RSScreenRenderNode>& curScreenNode)
44 {
45 if (pointWindow == nullptr || curScreenNode == nullptr) {
46 return;
47 }
48 auto dirtyManager = pointWindow->GetDirtyManager();
49 if (dirtyManager && pointWindow->GetHardCursorStatus()) {
50 if (!pointWindow->GetHardCursorLastStatus()) {
51 RectI lastFrameSurfacePos = curScreenNode->GetLastFrameSurfacePos(pointWindow->GetId());
52 curScreenNode->GetDirtyManager()->MergeDirtyRect(lastFrameSurfacePos);
53 }
54 auto pointerWindowDirtyRegion = dirtyManager->GetCurrentFrameDirtyRegion();
55 if (!pointerWindowDirtyRegion.IsEmpty()) {
56 curScreenNode->GetDirtyManager()->MergeHwcDirtyRect(pointerWindowDirtyRegion);
57 dirtyManager->SetCurrentFrameDirtyRect(RectI());
58 isNeedForceCommitByPointer_ = true;
59 } else {
60 isNeedForceCommitByPointer_ = false;
61 }
62 }
63 }
64
GetHardCursorEnabledPass()65 bool RSPointerWindowManager::GetHardCursorEnabledPass()
66 {
67 auto hardCursorFeatureParam = GraphicFeatureParamManager::GetInstance().GetFeatureParam("HardCursorConfig");
68 auto hardCursorFeature = std::static_pointer_cast<HardCursorParam>(hardCursorFeatureParam);
69 if (hardCursorFeature != nullptr) {
70 return hardCursorFeature->IsHardCursorEnable();
71 }
72 return false;
73 }
74
UpdatePointerInfo()75 void RSPointerWindowManager::UpdatePointerInfo()
76 {
77 #ifdef RS_ENABLE_GPU
78 int64_t rsNodeId = 0;
79 BoundParam boundTemp = {0.0f, 0.0f, 0.0f, 0.0f};
80 {
81 std::lock_guard<std::mutex> lock(mtx_);
82 if (!BoundHasUpdateCompareChange(true, false)) {
83 return;
84 }
85 rsNodeId = GetRsNodeId();
86 boundTemp = GetBound();
87 }
88
89 if (rsNodeId <= 0) {
90 return;
91 }
92
93 // prepare
94 auto node = RSMainThread::Instance()->GetContext().GetNodeMap().GetRenderNode(rsNodeId);
95 if (node == nullptr) {
96 return;
97 }
98 auto& properties = node->GetMutableRenderProperties();
99 properties.SetBounds({boundTemp.x, boundTemp.y, boundTemp.z, boundTemp.w});
100 node->SetDirty();
101 properties.OnApplyModifiers();
102 node->OnApplyModifiers();
103 node->AddToPendingSyncList();
104
105 // 1.Set TotalMatrix
106 auto surfaceNode = node->ReinterpretCastTo<RSSurfaceRenderNode>();
107 if (surfaceNode == nullptr) {
108 return;
109 }
110 RSUniHwcComputeUtil::UpdateHwcNodeProperty(surfaceNode);
111
112 // 2.update (layerInfo.matrix = TotalMatrix)
113 if (surfaceNode->GetScreenId() != INVALID_SCREEN_ID) {
114 auto screenManager = CreateOrGetScreenManager();
115 if (!screenManager) {
116 RS_LOGE("RSPointerWindowManager::UpdatePointerInfo screenManager is null!");
117 return;
118 }
119 auto screenInfo = screenManager->QueryScreenInfo(surfaceNode->GetScreenId());
120 auto transform = RSUniHwcComputeUtil::GetLayerTransform(*surfaceNode, screenInfo);
121 surfaceNode->UpdateHwcNodeLayerInfo(transform, isPointerEnableHwc_);
122 }
123 #endif
124 }
125
SetHwcNodeBounds(int64_t rsNodeId,float positionX,float positionY,float positionZ,float positionW)126 void RSPointerWindowManager::SetHwcNodeBounds(int64_t rsNodeId, float positionX, float positionY,
127 float positionZ, float positionW)
128 {
129 #ifdef RS_ENABLE_GPU
130 // record status here
131 {
132 std::lock_guard<std::mutex> lock(mtx_);
133 SetBound({positionX, positionY, positionZ, positionW});
134 SetRsNodeId(rsNodeId);
135 }
136 SetBoundHasUpdate(true);
137 #endif
138 }
139
SetHardCursorNodeInfo(std::shared_ptr<RSSurfaceRenderNode> hardCursorNode)140 void RSPointerWindowManager::SetHardCursorNodeInfo(std::shared_ptr<RSSurfaceRenderNode> hardCursorNode)
141 {
142 if (!hardCursorNode) {
143 return;
144 }
145 if (!hardCursorNode->IsHardwareEnabledTopSurface() ||
146 (!hardCursorNode->ShouldPaint() && !hardCursorNode->GetHardCursorStatus())) {
147 return;
148 }
149 if (hardCursorNode->IsOnTheTree()) {
150 auto nodeId = hardCursorNode->GetId();
151 hardCursorNodeMap_.emplace(nodeId, hardCursorNode);
152 }
153 }
154
GetHardCursorNode() const155 const std::map<NodeId, std::shared_ptr<RSSurfaceRenderNode>>& RSPointerWindowManager::GetHardCursorNode() const
156 {
157 return hardCursorNodeMap_;
158 }
159
HardCursorCreateLayerForDirect(std::shared_ptr<RSProcessor> processor)160 void RSPointerWindowManager::HardCursorCreateLayerForDirect(std::shared_ptr<RSProcessor> processor)
161 {
162 #ifdef RS_ENABLE_GPU
163 auto& hardCursorNodeMap = GetHardCursorNode();
164 for (auto& [_, hardCursorNode] : hardCursorNodeMap) {
165 if (hardCursorNode && hardCursorNode->IsHardwareEnabledTopSurface()) {
166 auto surfaceHandler = hardCursorNode->GetRSSurfaceHandler();
167 if (!surfaceHandler) {
168 continue;
169 }
170 auto params = static_cast<RSSurfaceRenderParams *>(hardCursorNode->GetStagingRenderParams().get());
171 if (!params) {
172 continue;
173 }
174 if (!surfaceHandler->IsCurrentFrameBufferConsumed() && params->GetPreBuffer() != nullptr) {
175 params->SetPreBuffer(nullptr);
176 hardCursorNode->AddToPendingSyncList();
177 }
178 processor->CreateLayer(*hardCursorNode, *params);
179 }
180 }
181 #endif
182 }
183
CheckHardCursorSupport(uint32_t screenId)184 bool RSPointerWindowManager::CheckHardCursorSupport(uint32_t screenId)
185 {
186 if (!isHardCursorEnable_) {
187 return false;
188 }
189 auto screenManager = CreateOrGetScreenManager();
190 if (!screenManager) {
191 return false;
192 }
193 return screenManager->GetDisplayPropertyForHardCursor(screenId);
194 }
195
HasMirrorDisplay() const196 bool RSPointerWindowManager::HasMirrorDisplay() const
197 {
198 const std::shared_ptr<RSBaseRenderNode> rootNode =
199 RSMainThread::Instance()->GetContext().GetGlobalRootRenderNode();
200 if (rootNode == nullptr || rootNode->GetChildrenCount() <= 1) {
201 return false;
202 }
203 for (auto& child : *rootNode->GetSortedChildren()) {
204 if (!child || !child->IsInstanceOf<RSScreenRenderNode>()) {
205 continue;
206 }
207 auto screenNode = child->ReinterpretCastTo<RSScreenRenderNode>();
208 if (!screenNode) {
209 continue;
210 }
211 if (screenNode->IsMirrorScreen()) {
212 return true;
213 }
214 }
215 return false;
216 }
217
CollectAllHardCursor(RSSurfaceRenderNode & hardCursorNode,std::shared_ptr<RSScreenRenderNode> & curScreenNode,std::shared_ptr<RSLogicalDisplayRenderNode> & curDisplayNode)218 void RSPointerWindowManager::CollectAllHardCursor(
219 RSSurfaceRenderNode& hardCursorNode, std::shared_ptr<RSScreenRenderNode>& curScreenNode,
220 std::shared_ptr<RSLogicalDisplayRenderNode>& curDisplayNode)
221 {
222 if (hardCursorNode.IsHardwareEnabledTopSurface() &&
223 (hardCursorNode.ShouldPaint() || hardCursorNode.GetHardCursorStatus())) {
224 auto surfaceNodeDrawable =
225 std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(hardCursorNode.GetRenderDrawable());
226 if (surfaceNodeDrawable && hardCursorNode.IsOnTheTree()) {
227 hardCursorDrawableVec_.emplace_back(curScreenNode->GetId(),
228 curDisplayNode->GetId(), hardCursorNode.GetRenderDrawable());
229 }
230 }
231 }
232
GetHardCursorDrawable(NodeId id)233 std::shared_ptr<DrawableV2::RSSurfaceRenderNodeDrawable> RSPointerWindowManager::GetHardCursorDrawable(NodeId id)
234 {
235 auto& renderThreadParams = RSUniRenderThread::Instance().GetRSRenderThreadParams();
236 if (!renderThreadParams) {
237 return nullptr;
238 }
239 auto& hardCursorDrawables = renderThreadParams->GetHardCursorDrawables();
240 if (hardCursorDrawables.empty()) {
241 return nullptr;
242 }
243 auto iter = std::find_if(hardCursorDrawables.begin(), hardCursorDrawables.end(), [id](const auto& node) {
244 return id == std::get<0>(node);
245 });
246 if (iter == hardCursorDrawables.end()) {
247 return nullptr;
248 }
249 auto& hardCursorDrawable = std::get<2>(*iter);
250 if (!hardCursorDrawable) {
251 return nullptr;
252 }
253 auto surfaceParams = static_cast<RSSurfaceRenderParams*>(hardCursorDrawable->GetRenderParams().get());
254 if (!surfaceParams) {
255 return nullptr;
256 }
257 auto surfaceDrawable = std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(hardCursorDrawable);
258 if (surfaceDrawable && surfaceParams->GetHardCursorStatus()) {
259 return std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(surfaceDrawable);
260 }
261 return nullptr;
262 }
263
CheckHardCursorValid(const RSSurfaceRenderNode & node)264 void RSPointerWindowManager::CheckHardCursorValid(const RSSurfaceRenderNode& node)
265 {
266 if (!node.GetHardCursorStatus()) {
267 return;
268 }
269 // DSS Hardware don't support the synthesis of layers with length and width not larger than 2
270 auto srcRect = node.GetSrcRect();
271 if (srcRect.GetWidth() <= MIN_LAYER_WIDTH || srcRect.GetHeight() <= MIN_LAYER_WIDTH) {
272 const auto& property = node.GetRenderProperties();
273 auto buffer = node.GetRSSurfaceHandler()->GetBuffer();
274 if (buffer == nullptr) {
275 RS_LOGE("RSPointerWindowManager::CheckHardCursorValid: buffer is nullptr");
276 return;
277 }
278 auto bufferWidth = buffer->GetSurfaceBufferWidth();
279 auto bufferHeight = buffer->GetSurfaceBufferHeight();
280 const auto boundsWidth = property.GetBoundsWidth();
281 const auto boundsHeight = property.GetBoundsHeight();
282 RS_LOGE("hardcursor srcRect error, %{public}d, %{public}d, %{public}f, %{public}f",
283 bufferWidth, bufferHeight, boundsWidth, boundsHeight);
284 }
285 }
286 } // namespace Rosen
287 } // namespace OHOS