[dali_2.1.6] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / canvas-view / canvas-view-rasterize-thread.cpp
1 /*
2  * Copyright (c) 2021 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 "canvas-view-rasterize-thread.h"
20
21 // EXTERNAL INCLUDES
22 #include <dali/devel-api/adaptor-framework/thread-settings.h>
23 #include <dali/integration-api/adaptor-framework/adaptor.h>
24
25 namespace Dali
26 {
27 namespace Toolkit
28 {
29 namespace Internal
30 {
31 CanvasRendererRasterizingTask::CanvasRendererRasterizingTask(CanvasView* canvasView, CanvasRenderer canvasRenderer)
32 : mCanvasView(canvasView),
33   mCanvasRenderer(canvasRenderer),
34   mRasterizedTexture()
35 {
36 }
37
38 bool CanvasRendererRasterizingTask::Rasterize()
39 {
40   if(mCanvasRenderer && mCanvasRenderer.Rasterize())
41   {
42     return true;
43   }
44   return false;
45 }
46
47 CanvasView* CanvasRendererRasterizingTask::GetCanvasView() const
48 {
49   return mCanvasView.Get();
50 }
51
52 Texture CanvasRendererRasterizingTask::GetRasterizedTexture()
53 {
54   return mCanvasRenderer.GetRasterizedTexture();
55 }
56
57 CanvasViewRasterizeThread::CanvasViewRasterizeThread()
58 : mTrigger(new EventThreadCallback(MakeCallback(this, &CanvasViewRasterizeThread::ApplyRasterized))),
59   mLogFactory(Dali::Adaptor::Get().GetLogFactory()),
60   mProcessorRegistered(false),
61   mRasterizationCompletedSignal()
62 {
63 }
64
65 CanvasViewRasterizeThread::~CanvasViewRasterizeThread()
66 {
67   if(mProcessorRegistered && Adaptor::IsAvailable())
68   {
69     Adaptor::Get().UnregisterProcessor(*this);
70   }
71 }
72
73 void CanvasViewRasterizeThread::TerminateThread(CanvasViewRasterizeThread*& thread)
74 {
75   if(thread)
76   {
77     // add an empty task would stop the thread from conditional wait.
78     thread->AddTask(CanvasRendererRasterizingTaskPtr());
79     // stop the thread
80     thread->Join();
81     // delete the thread
82     delete thread;
83     thread = NULL;
84   }
85 }
86
87 void CanvasViewRasterizeThread::AddTask(CanvasRendererRasterizingTaskPtr task)
88 {
89   bool wasEmpty = false;
90
91   {
92     // Lock while adding task to the queue
93     ConditionalWait::ScopedLock lock(mConditionalWait);
94     wasEmpty = mRasterizeTasks.empty();
95     if(!wasEmpty && task)
96     {
97       // Remove the tasks with the same renderer.
98       // Older task which waiting to rasterize and apply the svg to the same renderer is expired.
99       for(std::vector<CanvasRendererRasterizingTaskPtr>::iterator it = mRasterizeTasks.begin(), endIt = mRasterizeTasks.end(); it != endIt; ++it)
100       {
101         if((*it) && (*it)->GetCanvasView() == task->GetCanvasView()) //Need
102         {
103           mRasterizeTasks.erase(it);
104           break;
105         }
106       }
107     }
108     mRasterizeTasks.push_back(task);
109
110     if(!mProcessorRegistered && Adaptor::IsAvailable())
111     {
112       Adaptor::Get().RegisterProcessor(*this);
113       mProcessorRegistered = true;
114     }
115   }
116
117   if(wasEmpty)
118   {
119     // wake up the image loading thread
120     mConditionalWait.Notify();
121   }
122 }
123
124 CanvasRendererRasterizingTaskPtr CanvasViewRasterizeThread::NextCompletedTask()
125 {
126   // Lock while popping task out from the queue
127   Mutex::ScopedLock lock(mMutex);
128
129   if(mCompletedTasks.empty())
130   {
131     return CanvasRendererRasterizingTaskPtr();
132   }
133
134   std::vector<CanvasRendererRasterizingTaskPtr>::iterator next     = mCompletedTasks.begin();
135   CanvasRendererRasterizingTaskPtr                        nextTask = *next;
136   mCompletedTasks.erase(next);
137
138   return nextTask;
139 }
140
141 void CanvasViewRasterizeThread::RemoveTask(CanvasView* canvasView)
142 {
143   // Lock while remove task from the queue
144   ConditionalWait::ScopedLock lock(mConditionalWait);
145   if(!mRasterizeTasks.empty())
146   {
147     for(std::vector<CanvasRendererRasterizingTaskPtr>::iterator it = mRasterizeTasks.begin(), endIt = mRasterizeTasks.end(); it != endIt; ++it)
148     {
149       if((*it) && (*it)->GetCanvasView() == canvasView)
150       {
151         mRasterizeTasks.erase(it);
152         break;
153       }
154     }
155   }
156
157   UnregisterProcessor();
158 }
159
160 CanvasRendererRasterizingTaskPtr CanvasViewRasterizeThread::NextTaskToProcess()
161 {
162   // Lock while popping task out from the queue
163   ConditionalWait::ScopedLock lock(mConditionalWait);
164
165   // conditional wait
166   while(mRasterizeTasks.empty())
167   {
168     mConditionalWait.Wait(lock);
169   }
170
171   // pop out the next task from the queue
172   std::vector<CanvasRendererRasterizingTaskPtr>::iterator next     = mRasterizeTasks.begin();
173   CanvasRendererRasterizingTaskPtr                        nextTask = *next;
174   mRasterizeTasks.erase(next);
175
176   return nextTask;
177 }
178
179 void CanvasViewRasterizeThread::AddCompletedTask(CanvasRendererRasterizingTaskPtr task)
180 {
181   // Lock while adding task to the queue
182   Mutex::ScopedLock lock(mMutex);
183   mCompletedTasks.push_back(task);
184
185   // wake up the main thread
186   mTrigger->Trigger();
187 }
188
189 void CanvasViewRasterizeThread::Run()
190 {
191   SetThreadName("CanvasViewThread");
192   mLogFactory.InstallLogFunction();
193
194   while(CanvasRendererRasterizingTaskPtr task = NextTaskToProcess())
195   {
196     if(task->Rasterize())
197     {
198       AddCompletedTask(task);
199     }
200   }
201 }
202
203 void CanvasViewRasterizeThread::ApplyRasterized()
204 {
205   while(CanvasRendererRasterizingTaskPtr task = NextCompletedTask())
206   {
207     RasterizationCompletedSignal().Emit(task->GetRasterizedTexture()); // Here texture get
208   }
209
210   UnregisterProcessor();
211 }
212
213 void CanvasViewRasterizeThread::Process(bool postProcessor)
214 {
215   ApplyRasterized();
216 }
217
218 CanvasViewRasterizeThread::RasterizationCompletedSignalType& CanvasViewRasterizeThread::RasterizationCompletedSignal()
219 {
220   return mRasterizationCompletedSignal;
221 }
222
223 void CanvasViewRasterizeThread::UnregisterProcessor()
224 {
225   if(mProcessorRegistered)
226   {
227     if(mRasterizeTasks.empty() && mCompletedTasks.empty() && Adaptor::IsAvailable())
228     {
229       Adaptor::Get().UnregisterProcessor(*this);
230       mProcessorRegistered = false;
231     }
232   }
233 }
234
235 } // namespace Internal
236
237 } // namespace Toolkit
238
239 } // namespace Dali