1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "property/rs_point_light_manager.h"
17
18 #include "common/rs_common_def.h"
19 #include "common/rs_obj_abs_geometry.h"
20 #include "pipeline/rs_render_node.h"
21 #include "property/rs_properties_def.h"
22 #include "screen_manager/screen_types.h"
23
24 namespace OHOS {
25 namespace Rosen {
26 constexpr int TWO = 2;
27
Instance()28 RSPointLightManager* RSPointLightManager::Instance()
29 {
30 static RSPointLightManager instance;
31 return &instance;
32 }
33
RegisterLightSource(const std::shared_ptr<RSRenderNode> & renderNode)34 void RSPointLightManager::RegisterLightSource(const std::shared_ptr<RSRenderNode>& renderNode)
35 {
36 NodeId nodeId = renderNode->GetId();
37 lightSourceNodeMap_.emplace(nodeId, renderNode->weak_from_this());
38 }
39
RegisterIlluminated(const std::shared_ptr<RSRenderNode> & renderNode)40 void RSPointLightManager::RegisterIlluminated(const std::shared_ptr<RSRenderNode>& renderNode)
41 {
42 NodeId nodeId = renderNode->GetId();
43 illuminatedNodeMap_.emplace(nodeId, renderNode->weak_from_this());
44 }
45
UnRegisterLightSource(const std::shared_ptr<RSRenderNode> & renderNode)46 void RSPointLightManager::UnRegisterLightSource(const std::shared_ptr<RSRenderNode>& renderNode)
47 {
48 NodeId nodeId = renderNode->GetId();
49 lightSourceNodeMap_.erase(nodeId);
50 }
UnRegisterIlluminated(const std::shared_ptr<RSRenderNode> & renderNode)51 void RSPointLightManager::UnRegisterIlluminated(const std::shared_ptr<RSRenderNode>& renderNode)
52 {
53 NodeId nodeId = renderNode->GetId();
54 illuminatedNodeMap_.erase(nodeId);
55 }
AddDirtyLightSource(std::weak_ptr<RSRenderNode> renderNode)56 void RSPointLightManager::AddDirtyLightSource(std::weak_ptr<RSRenderNode> renderNode)
57 {
58 dirtyLightSourceList_.emplace_back(renderNode);
59 }
AddDirtyIlluminated(std::weak_ptr<RSRenderNode> renderNode)60 void RSPointLightManager::AddDirtyIlluminated(std::weak_ptr<RSRenderNode> renderNode)
61 {
62 dirtyIlluminatedList_.emplace_back(renderNode);
63 }
ClearDirtyList()64 void RSPointLightManager::ClearDirtyList()
65 {
66 dirtyLightSourceList_.clear();
67 dirtyIlluminatedList_.clear();
68 }
PrepareLight()69 void RSPointLightManager::PrepareLight()
70 {
71 for (auto &[_, weakPtr] : illuminatedNodeMap_) {
72 if (auto node = weakPtr.lock()) {
73 node->UpdatePointLightDirtySlot();
74 }
75 }
76 if (lightSourceNodeMap_.empty() || illuminatedNodeMap_.empty()) {
77 ClearDirtyList();
78 return;
79 }
80 if ((dirtyIlluminatedList_.empty() && dirtyLightSourceList_.empty())) {
81 return;
82 }
83 for (const auto& illuminatedWeakPtr : dirtyIlluminatedList_) {
84 auto illuminatedNodePtr = illuminatedWeakPtr.lock();
85 if (illuminatedNodePtr) {
86 illuminatedNodePtr->GetRenderProperties().GetIlluminated()->ClearLightSourcesAndPosMap();
87 }
88 }
89 PrepareLight(lightSourceNodeMap_, dirtyIlluminatedList_, false);
90 PrepareLight(illuminatedNodeMap_, dirtyLightSourceList_, true);
91 ClearDirtyList();
92 }
PrepareLight(std::unordered_map<NodeId,std::weak_ptr<RSRenderNode>> & map,std::vector<std::weak_ptr<RSRenderNode>> & dirtyList,bool isLightSourceDirty)93 void RSPointLightManager::PrepareLight(std::unordered_map<NodeId, std::weak_ptr<RSRenderNode>>& map,
94 std::vector<std::weak_ptr<RSRenderNode>>& dirtyList, bool isLightSourceDirty)
95 {
96 EraseIf(map, [this, isLightSourceDirty, &dirtyList](const auto& pair) -> bool {
97 auto mapElm = pair.second.lock();
98 if (!mapElm) {
99 return true;
100 }
101 if (!mapElm->IsOnTheTree()) { // skip check when node is not on the tree
102 return false;
103 }
104 for (const auto& weakPtr : dirtyList) {
105 auto dirtyNodePtr = weakPtr.lock();
106 if (!dirtyNodePtr) {
107 continue;
108 }
109 std::shared_ptr<RSRenderNode> lightSourceNode = isLightSourceDirty ? dirtyNodePtr : mapElm;
110 std::shared_ptr<RSRenderNode> illuminatedNode = isLightSourceDirty ? mapElm : dirtyNodePtr;
111 CheckIlluminated(lightSourceNode, illuminatedNode);
112 }
113 return false;
114 });
115 }
CheckIlluminated(const std::shared_ptr<RSRenderNode> & lightSourceNode,const std::shared_ptr<RSRenderNode> & illuminatedNode)116 void RSPointLightManager::CheckIlluminated(
117 const std::shared_ptr<RSRenderNode>& lightSourceNode, const std::shared_ptr<RSRenderNode>& illuminatedNode)
118 {
119 const auto& geoPtr = (illuminatedNode->GetRenderProperties().GetBoundsGeometry());
120 auto lightSourcePtr = lightSourceNode->GetRenderProperties().GetLightSource();
121 if (!geoPtr || geoPtr->IsEmpty() || !lightSourcePtr) {
122 return;
123 }
124 RectI illuminatedAbsRect = geoPtr->GetAbsRect();
125 int radius = static_cast<int>(lightSourcePtr->GetLightRadius());
126 auto illuminatedRange = RectI(illuminatedAbsRect.left_ - radius, illuminatedAbsRect.top_ - radius,
127 illuminatedAbsRect.width_ + TWO * radius, illuminatedAbsRect.height_ + TWO * radius);
128 const auto& lightSourceAbsPosition = lightSourcePtr->GetAbsLightPosition();
129 auto lightAbsPositionX = static_cast<int>(lightSourceAbsPosition[0]);
130 auto lightAbsPositionY = static_cast<int>(lightSourceAbsPosition[1]);
131 auto rotation = GetScreenRotation();
132 auto inIlluminatedRange = false;
133 if (rotation == ScreenRotation::ROTATION_0 || rotation == ScreenRotation::ROTATION_180) {
134 inIlluminatedRange = illuminatedRange.Intersect(lightAbsPositionX, lightAbsPositionY);
135 } else if (rotation == ScreenRotation::ROTATION_90 || rotation == ScreenRotation::ROTATION_270) {
136 inIlluminatedRange = illuminatedRange.Intersect(lightAbsPositionY, lightAbsPositionX);
137 }
138 auto illuminatedRootNodeId = illuminatedNode->GetInstanceRootNodeId();
139 auto lightSourceRootNodeId = lightSourceNode->GetInstanceRootNodeId();
140 if (inIlluminatedRange && illuminatedRootNodeId == lightSourceRootNodeId) {
141 auto lightPos = CalculateLightPosForIlluminated(*lightSourcePtr, geoPtr->GetAbsRect());
142 illuminatedNode->GetRenderProperties().GetIlluminated()->AddLightSourcesAndPos(lightSourcePtr, lightPos);
143 illuminatedNode->SetDirty();
144 }
145 }
146
CalculateLightPosForIlluminated(const RSLightSource & lightSource,const RectI & illuminatedAbsRect)147 Vector4f RSPointLightManager::CalculateLightPosForIlluminated(
148 const RSLightSource& lightSource, const RectI& illuminatedAbsRect)
149 {
150 Vector4f lightPos;
151 auto lightSourceAbsPosition = lightSource.GetAbsLightPosition();
152 auto lightPosition = lightSource.GetLightPosition();
153 auto rotation = GetScreenRotation();
154 switch (rotation) {
155 case ScreenRotation::ROTATION_0:
156 lightPos.x_ = lightSourceAbsPosition.x_ - illuminatedAbsRect.GetLeft();
157 lightPos.y_ = lightSourceAbsPosition.y_ - illuminatedAbsRect.GetTop();
158 break;
159 case ScreenRotation::ROTATION_90:
160 lightPos.x_ = illuminatedAbsRect.GetBottom() - lightSourceAbsPosition.x_;
161 lightPos.y_ = lightSourceAbsPosition.y_ - illuminatedAbsRect.GetLeft();
162 break;
163 case ScreenRotation::ROTATION_180:
164 lightPos.x_ = illuminatedAbsRect.GetRight() - lightSourceAbsPosition.x_;
165 lightPos.y_ = illuminatedAbsRect.GetBottom() - lightSourceAbsPosition.y_;
166 break;
167 case ScreenRotation::ROTATION_270:
168 lightPos.x_ = lightSourceAbsPosition.x_ - illuminatedAbsRect.GetTop();
169 lightPos.y_ = illuminatedAbsRect.GetRight() - lightSourceAbsPosition.y_;
170 break;
171 default:
172 break;
173 }
174 lightPos.z_ = lightPosition.z_;
175 lightPos.w_ = lightPosition.w_;
176 return lightPos;
177 }
178
179 } // namespace Rosen
180 } // namespace OHOS