2 * Copyright (c) 2021 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/system/common/capture-impl.h>
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>
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>
35 unsigned int TIME_OUT_DURATION = 1000;
45 : mQuality(DEFAULT_QUALITY),
48 mNativeImageSourcePtr(NULL),
53 Capture::Capture(Dali::CameraActor cameraActor)
54 : mQuality(DEFAULT_QUALITY),
55 mCameraActor(cameraActor),
58 mNativeImageSourcePtr(NULL),
65 DeleteNativeImageSource();
68 CapturePtr Capture::New()
70 CapturePtr pWorker = new Capture();
75 CapturePtr Capture::New(Dali::CameraActor cameraActor)
77 CapturePtr pWorker = new Capture(cameraActor);
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)
85 Start(source, position, size, path, clearColor);
88 void Capture::Start(Dali::Actor source, const Dali::Vector2& position, const Dali::Vector2& size, const std::string& path, const Dali::Vector4& clearColor)
90 DALI_ASSERT_ALWAYS(path.size() > 4 && "Path is invalid.");
92 // Increase the reference count focely to avoid application mistake.
101 DALI_ASSERT_ALWAYS(source && "Source is NULL.");
104 SetupResources(position, size, clearColor, source);
107 void Capture::SetImageQuality(uint32_t quality)
112 Dali::NativeImageSourcePtr Capture::GetNativeImageSource() const
114 return mNativeImageSourcePtr;
117 Dali::Capture::CaptureFinishedSignalType& Capture::FinishedSignal()
119 return mFinishedSignal;
122 void Capture::CreateNativeImageSource(const Vector2& size)
124 Dali::Adaptor& adaptor = Dali::Adaptor::Get();
126 DALI_ASSERT_ALWAYS(adaptor.IsAvailable() && "Dali::Adaptor is not available.");
128 DALI_ASSERT_ALWAYS(!mNativeImageSourcePtr && "NativeImageSource is already created.");
130 // create the NativeImageSource object with our surface
131 mNativeImageSourcePtr = Dali::NativeImageSource::New(size.width, size.height, Dali::NativeImageSource::COLOR_DEPTH_DEFAULT);
134 void Capture::DeleteNativeImageSource()
136 mNativeImageSourcePtr.Reset();
139 bool Capture::IsNativeImageSourceCreated()
141 return mNativeImageSourcePtr;
144 void Capture::CreateFrameBuffer()
146 DALI_ASSERT_ALWAYS(mNativeImageSourcePtr && "NativeImageSource is NULL.");
148 DALI_ASSERT_ALWAYS(!mFrameBuffer && "FrameBuffer is already created.");
150 mNativeTexture = Dali::Texture::New(*mNativeImageSourcePtr);
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);
158 void Capture::DeleteFrameBuffer()
160 DALI_ASSERT_ALWAYS(mFrameBuffer && "FrameBuffer is NULL.");
162 mFrameBuffer.Reset();
163 mNativeTexture.Reset();
166 bool Capture::IsFrameBufferCreated()
171 void Capture::SetupRenderTask(const Dali::Vector2& position, const Dali::Vector2& size, Dali::Actor source, const Dali::Vector4& clearColor)
173 DALI_ASSERT_ALWAYS(source && "Source is empty.");
175 Dali::Window window = DevelWindow::Get(source);
178 DALI_LOG_ERROR("The source is not added on the window\n");
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);
196 window.Add(mCameraActor);
198 DALI_ASSERT_ALWAYS(mFrameBuffer && "Framebuffer is NULL.");
200 DALI_ASSERT_ALWAYS(!mRenderTask && "RenderTask is already created.");
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);
215 mTimer = Dali::Timer::New(TIME_OUT_DURATION);
216 mTimer.TickSignal().Connect(this, &Capture::OnTimeOut);
220 void Capture::UnsetRenderTask()
222 DALI_ASSERT_ALWAYS(mCameraActor && "CameraActor is NULL.");
226 mCameraActor.Unparent();
227 mCameraActor.Reset();
229 DALI_ASSERT_ALWAYS(mRenderTask && "RenderTask is NULL.");
231 Dali::Window window = DevelWindow::Get(mSource);
232 Dali::RenderTaskList taskList = window.GetRenderTaskList();
233 taskList.RemoveTask(mRenderTask);
238 bool Capture::IsRenderTaskSetup()
240 return mCameraActor && mRenderTask;
243 void Capture::SetupResources(const Dali::Vector2& position, const Dali::Vector2& size, const Dali::Vector4& clearColor, Dali::Actor source)
245 CreateNativeImageSource(size);
249 SetupRenderTask(position, size, source, clearColor);
252 void Capture::UnsetResources()
254 if(IsRenderTaskSetup())
259 if(IsFrameBufferCreated())
265 void Capture::OnRenderFinished(Dali::RenderTask& task)
267 Dali::Capture::FinishState state = Dali::Capture::FinishState::SUCCEEDED;
275 state = Dali::Capture::FinishState::FAILED;
276 DALI_LOG_ERROR("Fail to Capture Path[%s]", mPath.c_str());
280 Dali::Capture handle(this);
281 mFinishedSignal.Emit(handle, state);
285 // Decrease the reference count forcely. It is increased at Start().
289 bool Capture::OnTimeOut()
291 Dali::Capture::FinishState state = Dali::Capture::FinishState::FAILED;
293 Dali::Capture handle(this);
294 mFinishedSignal.Emit(handle, state);
298 // Decrease the reference count forcely. It is increased at Start().
304 bool Capture::SaveFile()
306 DALI_ASSERT_ALWAYS(mNativeImageSourcePtr && "mNativeImageSourcePtr is NULL");
308 return Dali::DevelNativeImageSource::EncodeToFile(*mNativeImageSourcePtr, mPath, mQuality);
311 } // End of namespace Adaptor
313 } // End of namespace Internal
315 } // End of namespace Dali