2 * Copyright (c) 2023 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali/internal/update/manager/frame-callback-processor.h>
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>
32 DALI_INIT_TRACE_FILTER(gTraceFilter, DALI_TRACE_PERFORMANCE_MARKER, false);
41 FrameCallbackProcessor::FrameCallbackProcessor(UpdateManager& updateManager, TransformManager& transformManager)
43 mUpdateManager(updateManager),
44 mTransformManager(transformManager),
46 mNodeHierarchyChanged(true)
50 FrameCallbackProcessor::~FrameCallbackProcessor() = default;
52 void FrameCallbackProcessor::AddFrameCallback(OwnerPointer<FrameCallback>& frameCallback, const Node* rootNode)
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.
56 SceneGraphTravelerPtr traveler = GetSceneGraphTraveler(&node);
58 frameCallback->ConnectToSceneGraph(mUpdateManager, mTransformManager, node, traveler);
60 mFrameCallbacks.emplace_back(frameCallback);
63 void FrameCallbackProcessor::RemoveFrameCallback(FrameCallbackInterface* frameCallback)
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());
70 void FrameCallbackProcessor::NotifyFrameCallback(FrameCallbackInterface* frameCallback, Dali::UpdateProxy::NotifySyncPoint syncPoint)
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())
76 (*iter)->Notify(syncPoint);
80 bool FrameCallbackProcessor::Update(BufferIndex bufferIndex, float elapsedSeconds)
82 bool keepRendering = false;
84 if(mNodeHierarchyChanged)
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();)
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)
94 iter = mTravelerMap.erase(iter);
98 if(iter->first->IsDescendentHierarchyChanged())
100 iter->second->NodeHierarchyChanged();
107 if(!mFrameCallbacks.empty())
109 DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_FRAME_CALLBACK_UPDATE", [&](std::ostringstream& oss) {
110 oss << "[" << mFrameCallbacks.size() << "]";
113 // If any of the FrameCallback::Update calls returns false, then they are no longer required & can be removed.
114 auto iter = std::remove_if(
115 mFrameCallbacks.begin(), mFrameCallbacks.end(), [&](OwnerPointer<FrameCallback>& frameCallback) {
116 FrameCallback::RequestFlags requests = frameCallback->Update(bufferIndex, elapsedSeconds, mNodeHierarchyChanged);
117 keepRendering |= (requests & FrameCallback::KEEP_RENDERING);
118 return (requests & FrameCallback::CONTINUE_CALLING) == 0;
120 mFrameCallbacks.erase(iter, mFrameCallbacks.end());
122 DALI_TRACE_END_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_FRAME_CALLBACK_UPDATE", [&](std::ostringstream& oss) {
123 oss << "[" << mFrameCallbacks.size() << "]";
127 mNodeHierarchyChanged = false;
129 return keepRendering;
132 SceneGraphTravelerPtr FrameCallbackProcessor::GetSceneGraphTraveler(Node* rootNode)
134 auto iter = mTravelerMap.find(rootNode);
136 if(iter != mTravelerMap.end())
138 // Check wheter traveler is invalidated or not
139 if(!iter->second->IsInvalidated())
145 mTravelerMap.erase(iter);
149 // Create new traveler and keep it.
150 return (mTravelerMap.insert({rootNode, new SceneGraphTraveler(*rootNode)})).first->second;
153 } // namespace SceneGraph
155 } // namespace Internal