2 * Copyright (c) 2020 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>
24 #include <dali/public-api/common/vector-wrapper.h>
25 #include <dali/public-api/render-tasks/render-task-list.h>
26 #include <dali/integration-api/debug.h>
29 #include <dali/integration-api/adaptor-framework/adaptor.h>
30 #include <dali/devel-api/adaptor-framework/native-image-source-devel.h>
31 #include <dali/devel-api/adaptor-framework/window-devel.h>
35 unsigned int TIME_OUT_DURATION = 1000;
48 : mQuality( DEFAULT_QUALITY ),
51 mNativeImageSourcePtr( NULL ),
56 Capture::Capture( Dali::CameraActor cameraActor )
57 : mQuality( DEFAULT_QUALITY ),
58 mCameraActor( cameraActor ),
61 mNativeImageSourcePtr( NULL ),
68 DeleteNativeImageSource();
71 CapturePtr Capture::New()
73 CapturePtr pWorker = new Capture();
78 CapturePtr Capture::New( Dali::CameraActor cameraActor )
80 CapturePtr pWorker = new Capture( cameraActor );
85 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 )
88 Start( source, position, size, path, clearColor );
91 void Capture::Start( Dali::Actor source, const Dali::Vector2& position, const Dali::Vector2& size, const std::string &path, const Dali::Vector4& clearColor )
93 DALI_ASSERT_ALWAYS(path.size() > 4 && "Path is invalid.");
95 // Increase the reference count focely to avoid application mistake.
99 if( mPath.size() > 0 )
104 DALI_ASSERT_ALWAYS(source && "Source is NULL.");
107 SetupResources( position, size, clearColor, source );
110 void Capture::SetImageQuality( uint32_t quality )
115 Dali::NativeImageSourcePtr Capture::GetNativeImageSource() const
117 return mNativeImageSourcePtr;
120 Dali::Capture::CaptureFinishedSignalType& Capture::FinishedSignal()
122 return mFinishedSignal;
125 void Capture::CreateNativeImageSource( const Vector2& size )
127 Dali::Adaptor& adaptor = Dali::Adaptor::Get();
129 DALI_ASSERT_ALWAYS(adaptor.IsAvailable() && "Dali::Adaptor is not available.");
131 DALI_ASSERT_ALWAYS(!mNativeImageSourcePtr && "NativeImageSource is already created.");
133 // create the NativeImageSource object with our surface
134 mNativeImageSourcePtr = Dali::NativeImageSource::New( size.width, size.height, Dali::NativeImageSource::COLOR_DEPTH_DEFAULT );
137 void Capture::DeleteNativeImageSource()
139 mNativeImageSourcePtr.Reset();
142 bool Capture::IsNativeImageSourceCreated()
144 return mNativeImageSourcePtr;
147 void Capture::CreateFrameBuffer()
149 DALI_ASSERT_ALWAYS(mNativeImageSourcePtr && "NativeImageSource is NULL.");
151 DALI_ASSERT_ALWAYS(!mFrameBuffer && "FrameBuffer is already created.");
153 mNativeTexture = Dali::Texture::New( *mNativeImageSourcePtr );
155 // Create a FrameBuffer object with depth attachments.
156 mFrameBuffer = Dali::FrameBuffer::New( mNativeTexture.GetWidth(), mNativeTexture.GetHeight(), Dali::FrameBuffer::Attachment::DEPTH );
157 // Add a color attachment to the FrameBuffer object.
158 mFrameBuffer.AttachColorTexture( mNativeTexture );
161 void Capture::DeleteFrameBuffer()
163 DALI_ASSERT_ALWAYS(mFrameBuffer && "FrameBuffer is NULL.");
165 mFrameBuffer.Reset();
166 mNativeTexture.Reset();
169 bool Capture::IsFrameBufferCreated()
174 void Capture::SetupRenderTask( const Dali::Vector2& position, const Dali::Vector2& size, Dali::Actor source, const Dali::Vector4& clearColor )
176 DALI_ASSERT_ALWAYS(source && "Source is empty.");
178 Dali::Window window = DevelWindow::Get( source );
181 DALI_LOG_ERROR("The source is not added on the window\n");
189 mCameraActor = Dali::CameraActor::New( size );
190 // Because input position and size are for 2 dimentional area,
191 // default z-directional position of the camera is required to be used for the new camera position.
192 float cameraDefaultZPosition = mCameraActor.GetProperty<float>( Dali::Actor::Property::POSITION_Z );
193 Vector2 positionTransition = position + size / 2;
194 mCameraActor.SetProperty( Dali::Actor::Property::POSITION, Vector3( positionTransition.x, positionTransition.y, cameraDefaultZPosition ) );
195 mCameraActor.SetProperty( Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT );
196 mCameraActor.SetProperty( Dali::Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER );
199 window.Add( mCameraActor );
201 DALI_ASSERT_ALWAYS(mFrameBuffer && "Framebuffer is NULL.");
203 DALI_ASSERT_ALWAYS(!mRenderTask && "RenderTask is already created.");
205 Dali::RenderTaskList taskList = window.GetRenderTaskList();
206 mRenderTask = taskList.CreateTask();
207 mRenderTask.SetRefreshRate( Dali::RenderTask::REFRESH_ONCE );
208 mRenderTask.SetSourceActor( source );
209 mRenderTask.SetCameraActor( mCameraActor );
210 mRenderTask.SetScreenToFrameBufferFunction( Dali::RenderTask::FULLSCREEN_FRAMEBUFFER_FUNCTION );
211 mRenderTask.SetFrameBuffer( mFrameBuffer );
212 mRenderTask.SetClearColor( clearColor );
213 mRenderTask.SetClearEnabled( true );
214 mRenderTask.SetProperty( Dali::RenderTask::Property::REQUIRES_SYNC, true );
215 mRenderTask.FinishedSignal().Connect( this, &Capture::OnRenderFinished );
216 mRenderTask.GetCameraActor().SetInvertYAxis( true );
218 mTimer = Dali::Timer::New( TIME_OUT_DURATION );
219 mTimer.TickSignal().Connect( this, &Capture::OnTimeOut );
223 void Capture::UnsetRenderTask()
225 DALI_ASSERT_ALWAYS(mCameraActor && "CameraActor is NULL.");
229 mCameraActor.Unparent();
230 mCameraActor.Reset();
232 DALI_ASSERT_ALWAYS( mRenderTask && "RenderTask is NULL." );
234 Dali::Window window = DevelWindow::Get( mSource );
235 Dali::RenderTaskList taskList = window.GetRenderTaskList();
236 taskList.RemoveTask( mRenderTask );
241 bool Capture::IsRenderTaskSetup()
243 return mCameraActor && mRenderTask;
246 void Capture::SetupResources( const Dali::Vector2& position, const Dali::Vector2& size, const Dali::Vector4& clearColor, Dali::Actor source )
248 CreateNativeImageSource( size );
252 SetupRenderTask( position, size, source, clearColor );
255 void Capture::UnsetResources()
257 if( IsRenderTaskSetup() )
262 if( IsFrameBufferCreated() )
268 void Capture::OnRenderFinished( Dali::RenderTask& task )
270 Dali::Capture::FinishState state = Dali::Capture::FinishState::SUCCEEDED;
278 state = Dali::Capture::FinishState::FAILED;
279 DALI_LOG_ERROR( "Fail to Capture Path[%s]", mPath.c_str() );
283 Dali::Capture handle( this );
284 mFinishedSignal.Emit( handle, state );
288 // Decrease the reference count forcely. It is increased at Start().
292 bool Capture::OnTimeOut()
294 Dali::Capture::FinishState state = Dali::Capture::FinishState::FAILED;
296 Dali::Capture handle( this );
297 mFinishedSignal.Emit( handle, state );
301 // Decrease the reference count forcely. It is increased at Start().
307 bool Capture::SaveFile()
309 DALI_ASSERT_ALWAYS(mNativeImageSourcePtr && "mNativeImageSourcePtr is NULL");
311 return Dali::DevelNativeImageSource::EncodeToFile( *mNativeImageSourcePtr, mPath, mQuality );
314 } // End of namespace Adaptor
316 } // End of namespace Internal
318 } // End of namespace Dali