afa480ecd8012618444eca7880cf711a528bea0d
[platform/core/uifw/dali-core.git] / dali / internal / update / manager / frame-callback-processor.cpp
1 /*
2  * Copyright (c) 2023 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/internal/update/manager/frame-callback-processor.h>
20
21 // EXTERNAL INCLUDES
22 #include <algorithm>
23
24 // INTERNAL INCLUDES
25 #include <dali/devel-api/update/frame-callback-interface.h>
26 #include <dali/devel-api/update/update-proxy.h>
27 #include <dali/integration-api/debug.h>
28 #include <dali/integration-api/trace.h>
29
30 namespace
31 {
32 DALI_INIT_TRACE_FILTER(gTraceFilter, DALI_TRACE_PERFORMANCE_MARKER, false);
33 } // namespace
34
35 namespace Dali
36 {
37 namespace Internal
38 {
39 namespace SceneGraph
40 {
41 FrameCallbackProcessor::FrameCallbackProcessor(UpdateManager& updateManager, TransformManager& transformManager)
42 : mFrameCallbacks(),
43   mUpdateManager(updateManager),
44   mTransformManager(transformManager),
45   mTravelerMap{},
46   mNodeHierarchyChanged(true)
47 {
48 }
49
50 FrameCallbackProcessor::~FrameCallbackProcessor() = default;
51
52 void FrameCallbackProcessor::AddFrameCallback(OwnerPointer<FrameCallback>& frameCallback, const Node* rootNode)
53 {
54   Node& node = const_cast<Node&>(*rootNode); // Was sent as const from event thread, we need to be able to use non-const version here.
55
56   SceneGraphTravelerPtr traveler = GetSceneGraphTraveler(&node);
57
58   frameCallback->ConnectToSceneGraph(mUpdateManager, mTransformManager, node, traveler);
59
60   mFrameCallbacks.emplace_back(frameCallback);
61 }
62
63 void FrameCallbackProcessor::RemoveFrameCallback(FrameCallbackInterface* frameCallback)
64 {
65   // Find and remove all frame-callbacks that use the given frame-callback-interface
66   auto iter = std::remove(mFrameCallbacks.begin(), mFrameCallbacks.end(), frameCallback);
67   mFrameCallbacks.erase(iter, mFrameCallbacks.end());
68 }
69
70 void FrameCallbackProcessor::NotifyFrameCallback(FrameCallbackInterface* frameCallback, Dali::UpdateProxy::NotifySyncPoint syncPoint)
71 {
72   // Ensure that frame callback is still valid before sending notification
73   auto iter = std::find(mFrameCallbacks.begin(), mFrameCallbacks.end(), frameCallback);
74   if(iter != mFrameCallbacks.end())
75   {
76     (*iter)->Notify(syncPoint);
77   }
78 }
79
80 bool FrameCallbackProcessor::Update(BufferIndex bufferIndex, float elapsedSeconds)
81 {
82   bool keepRendering = false;
83
84   if(mNodeHierarchyChanged)
85   {
86     DALI_LOG_DEBUG_INFO("Node hierarchy changed. Update traveler map\n");
87     // Clear node traveler
88     for(auto iter = mTravelerMap.begin(); iter != mTravelerMap.end();)
89     {
90       // We don't need to erase invalidated traveler always. Just erase now.
91       // Note : ReferenceCount == 1 mean, no frame callbacks use this traveler now. We can erase it.
92       if(iter->second->IsInvalidated() || iter->second->ReferenceCount() == 1u)
93       {
94         iter = mTravelerMap.erase(iter);
95       }
96       else
97       {
98         (iter++)->second->NodeHierarchyChanged();
99       }
100     }
101   }
102
103   if(!mFrameCallbacks.empty())
104   {
105     DALI_TRACE_SCOPE(gTraceFilter, "DALI_FRAME_CALLBACK_UPDATE");
106
107     // If any of the FrameCallback::Update calls returns false, then they are no longer required & can be removed.
108     auto iter = std::remove_if(
109       mFrameCallbacks.begin(), mFrameCallbacks.end(), [&](OwnerPointer<FrameCallback>& frameCallback) {
110         FrameCallback::RequestFlags requests = frameCallback->Update(bufferIndex, elapsedSeconds, mNodeHierarchyChanged);
111         keepRendering |= (requests & FrameCallback::KEEP_RENDERING);
112         return (requests & FrameCallback::CONTINUE_CALLING) == 0;
113       });
114     mFrameCallbacks.erase(iter, mFrameCallbacks.end());
115   }
116
117   mNodeHierarchyChanged = false;
118
119   return keepRendering;
120 }
121
122 SceneGraphTravelerPtr FrameCallbackProcessor::GetSceneGraphTraveler(Node* rootNode)
123 {
124   auto iter = mTravelerMap.find(rootNode);
125
126   if(iter != mTravelerMap.end())
127   {
128     // Check wheter traveler is invalidated or not
129     if(!iter->second->IsInvalidated())
130     {
131       return iter->second;
132     }
133     else
134     {
135       mTravelerMap.erase(iter);
136     }
137   }
138
139   // Create new traveler and keep it.
140   return (mTravelerMap.insert({rootNode, new SceneGraphTraveler(*rootNode)})).first->second;
141 }
142
143 } // namespace SceneGraph
144
145 } // namespace Internal
146
147 } // namespace Dali