atspi: remove undefined method
[platform/core/uifw/dali-adaptor.git] / dali / internal / system / common / capture-impl.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 <dali/internal/system/common/capture-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali/integration-api/debug.h>
23 #include <dali/public-api/common/vector-wrapper.h>
24 #include <dali/public-api/render-tasks/render-task-list.h>
25 #include <string.h>
26 #include <fstream>
27
28 // INTERNAL INCLUDES
29 #include <dali/devel-api/adaptor-framework/native-image-source-devel.h>
30 #include <dali/devel-api/adaptor-framework/window-devel.h>
31 #include <dali/integration-api/adaptor-framework/adaptor.h>
32
33 namespace
34 {
35 unsigned int TIME_OUT_DURATION = 1000;
36 }
37
38 namespace Dali
39 {
40 namespace Internal
41 {
42 namespace Adaptor
43 {
44 Capture::Capture()
45 : mQuality(DEFAULT_QUALITY),
46   mTimer(),
47   mPath(),
48   mNativeImageSourcePtr(NULL),
49   mFileSave(false)
50 {
51 }
52
53 Capture::Capture(Dali::CameraActor cameraActor)
54 : mQuality(DEFAULT_QUALITY),
55   mCameraActor(cameraActor),
56   mTimer(),
57   mPath(),
58   mNativeImageSourcePtr(NULL),
59   mFileSave(false)
60 {
61 }
62
63 Capture::~Capture()
64 {
65   DeleteNativeImageSource();
66 }
67
68 CapturePtr Capture::New()
69 {
70   CapturePtr pWorker = new Capture();
71
72   return pWorker;
73 }
74
75 CapturePtr Capture::New(Dali::CameraActor cameraActor)
76 {
77   CapturePtr pWorker = new Capture(cameraActor);
78
79   return pWorker;
80 }
81
82 void Capture::Start(Dali::Actor source, const Dali::Vector2& position, const Dali::Vector2& size, const std::string& path, const Dali::Vector4& clearColor, const uint32_t quality)
83 {
84   mQuality = quality;
85   Start(source, position, size, path, clearColor);
86 }
87
88 void Capture::Start(Dali::Actor source, const Dali::Vector2& position, const Dali::Vector2& size, const std::string& path, const Dali::Vector4& clearColor)
89 {
90   DALI_ASSERT_ALWAYS(path.size() > 4 && "Path is invalid.");
91
92   // Increase the reference count focely to avoid application mistake.
93   Reference();
94
95   mPath = path;
96   if(mPath.size() > 0)
97   {
98     mFileSave = true;
99   }
100
101   DALI_ASSERT_ALWAYS(source && "Source is NULL.");
102
103   UnsetResources();
104   SetupResources(position, size, clearColor, source);
105 }
106
107 void Capture::SetImageQuality(uint32_t quality)
108 {
109   mQuality = quality;
110 }
111
112 Dali::NativeImageSourcePtr Capture::GetNativeImageSource() const
113 {
114   return mNativeImageSourcePtr;
115 }
116
117 Dali::Capture::CaptureFinishedSignalType& Capture::FinishedSignal()
118 {
119   return mFinishedSignal;
120 }
121
122 void Capture::CreateNativeImageSource(const Vector2& size)
123 {
124   Dali::Adaptor& adaptor = Dali::Adaptor::Get();
125
126   DALI_ASSERT_ALWAYS(adaptor.IsAvailable() && "Dali::Adaptor is not available.");
127
128   DALI_ASSERT_ALWAYS(!mNativeImageSourcePtr && "NativeImageSource is already created.");
129
130   // create the NativeImageSource object with our surface
131   mNativeImageSourcePtr = Dali::NativeImageSource::New(size.width, size.height, Dali::NativeImageSource::COLOR_DEPTH_DEFAULT);
132 }
133
134 void Capture::DeleteNativeImageSource()
135 {
136   mNativeImageSourcePtr.Reset();
137 }
138
139 bool Capture::IsNativeImageSourceCreated()
140 {
141   return mNativeImageSourcePtr;
142 }
143
144 void Capture::CreateFrameBuffer()
145 {
146   DALI_ASSERT_ALWAYS(mNativeImageSourcePtr && "NativeImageSource is NULL.");
147
148   DALI_ASSERT_ALWAYS(!mFrameBuffer && "FrameBuffer is already created.");
149
150   mNativeTexture = Dali::Texture::New(*mNativeImageSourcePtr);
151
152   // Create a FrameBuffer object with depth attachments.
153   mFrameBuffer = Dali::FrameBuffer::New(mNativeTexture.GetWidth(), mNativeTexture.GetHeight(), Dali::FrameBuffer::Attachment::DEPTH);
154   // Add a color attachment to the FrameBuffer object.
155   mFrameBuffer.AttachColorTexture(mNativeTexture);
156 }
157
158 void Capture::DeleteFrameBuffer()
159 {
160   DALI_ASSERT_ALWAYS(mFrameBuffer && "FrameBuffer is NULL.");
161
162   mFrameBuffer.Reset();
163   mNativeTexture.Reset();
164 }
165
166 bool Capture::IsFrameBufferCreated()
167 {
168   return mFrameBuffer;
169 }
170
171 void Capture::SetupRenderTask(const Dali::Vector2& position, const Dali::Vector2& size, Dali::Actor source, const Dali::Vector4& clearColor)
172 {
173   DALI_ASSERT_ALWAYS(source && "Source is empty.");
174
175   Dali::Window window = DevelWindow::Get(source);
176   if(!window)
177   {
178     DALI_LOG_ERROR("The source is not added on the window\n");
179     return;
180   }
181
182   mSource = source;
183
184   if(!mCameraActor)
185   {
186     mCameraActor = Dali::CameraActor::New(size);
187     // Because input position and size are for 2 dimentional area,
188     // default z-directional position of the camera is required to be used for the new camera position.
189     float   cameraDefaultZPosition = mCameraActor.GetProperty<float>(Dali::Actor::Property::POSITION_Z);
190     Vector2 positionTransition     = position + size / 2;
191     mCameraActor.SetProperty(Dali::Actor::Property::POSITION, Vector3(positionTransition.x, positionTransition.y, cameraDefaultZPosition));
192     mCameraActor.SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
193     mCameraActor.SetProperty(Dali::Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
194   }
195
196   window.Add(mCameraActor);
197
198   DALI_ASSERT_ALWAYS(mFrameBuffer && "Framebuffer is NULL.");
199
200   DALI_ASSERT_ALWAYS(!mRenderTask && "RenderTask is already created.");
201
202   Dali::RenderTaskList taskList = window.GetRenderTaskList();
203   mRenderTask                   = taskList.CreateTask();
204   mRenderTask.SetRefreshRate(Dali::RenderTask::REFRESH_ONCE);
205   mRenderTask.SetSourceActor(source);
206   mRenderTask.SetCameraActor(mCameraActor);
207   mRenderTask.SetScreenToFrameBufferFunction(Dali::RenderTask::FULLSCREEN_FRAMEBUFFER_FUNCTION);
208   mRenderTask.SetFrameBuffer(mFrameBuffer);
209   mRenderTask.SetClearColor(clearColor);
210   mRenderTask.SetClearEnabled(true);
211   mRenderTask.SetProperty(Dali::RenderTask::Property::REQUIRES_SYNC, true);
212   mRenderTask.FinishedSignal().Connect(this, &Capture::OnRenderFinished);
213   mRenderTask.GetCameraActor().SetInvertYAxis(true);
214
215   mTimer = Dali::Timer::New(TIME_OUT_DURATION);
216   mTimer.TickSignal().Connect(this, &Capture::OnTimeOut);
217   mTimer.Start();
218 }
219
220 void Capture::UnsetRenderTask()
221 {
222   DALI_ASSERT_ALWAYS(mCameraActor && "CameraActor is NULL.");
223
224   mTimer.Reset();
225
226   mCameraActor.Unparent();
227   mCameraActor.Reset();
228
229   DALI_ASSERT_ALWAYS(mRenderTask && "RenderTask is NULL.");
230
231   Dali::Window         window   = DevelWindow::Get(mSource);
232   Dali::RenderTaskList taskList = window.GetRenderTaskList();
233   taskList.RemoveTask(mRenderTask);
234   mRenderTask.Reset();
235   mSource.Reset();
236 }
237
238 bool Capture::IsRenderTaskSetup()
239 {
240   return mCameraActor && mRenderTask;
241 }
242
243 void Capture::SetupResources(const Dali::Vector2& position, const Dali::Vector2& size, const Dali::Vector4& clearColor, Dali::Actor source)
244 {
245   CreateNativeImageSource(size);
246
247   CreateFrameBuffer();
248
249   SetupRenderTask(position, size, source, clearColor);
250 }
251
252 void Capture::UnsetResources()
253 {
254   if(IsRenderTaskSetup())
255   {
256     UnsetRenderTask();
257   }
258
259   if(IsFrameBufferCreated())
260   {
261     DeleteFrameBuffer();
262   }
263 }
264
265 void Capture::OnRenderFinished(Dali::RenderTask& task)
266 {
267   Dali::Capture::FinishState state = Dali::Capture::FinishState::SUCCEEDED;
268
269   mTimer.Stop();
270
271   if(mFileSave)
272   {
273     if(!SaveFile())
274     {
275       state = Dali::Capture::FinishState::FAILED;
276       DALI_LOG_ERROR("Fail to Capture Path[%s]", mPath.c_str());
277     }
278   }
279
280   Dali::Capture handle(this);
281   mFinishedSignal.Emit(handle, state);
282
283   UnsetResources();
284
285   // Decrease the reference count forcely. It is increased at Start().
286   Unreference();
287 }
288
289 bool Capture::OnTimeOut()
290 {
291   Dali::Capture::FinishState state = Dali::Capture::FinishState::FAILED;
292
293   Dali::Capture handle(this);
294   mFinishedSignal.Emit(handle, state);
295
296   UnsetResources();
297
298   // Decrease the reference count forcely. It is increased at Start().
299   Unreference();
300
301   return false;
302 }
303
304 bool Capture::SaveFile()
305 {
306   DALI_ASSERT_ALWAYS(mNativeImageSourcePtr && "mNativeImageSourcePtr is NULL");
307
308   return Dali::DevelNativeImageSource::EncodeToFile(*mNativeImageSourcePtr, mPath, mQuality);
309 }
310
311 } // End of namespace Adaptor
312
313 } // End of namespace Internal
314
315 } // End of namespace Dali