2 * Copyright (c) 2014 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 <capture-impl.h>
22 #include <dali/public-api/common/vector-wrapper.h>
23 #include <dali/public-api/render-tasks/render-task-list.h>
24 #include <dali/public-api/common/stage.h>
25 #include <dali/integration-api/debug.h>
34 unsigned int TIME_OUT_DURATION = 1000;
49 mNativeImageSourcePtr( NULL ),
54 Capture::Capture( Dali::CameraActor cameraActor )
55 : mCameraActor( cameraActor ),
58 mNativeImageSourcePtr( NULL ),
67 CapturePtr Capture::New()
69 CapturePtr pWorker = new Capture();
71 // Second-phase construction
72 pWorker->Initialize();
77 CapturePtr Capture::New( Dali::CameraActor cameraActor )
79 CapturePtr pWorker = new Capture( cameraActor );
81 // Second-phase construction
82 pWorker->Initialize();
87 void Capture::Start( Dali::Actor source, const Dali::Vector2& size, const std::string &path, const Dali::Vector4& clearColor )
89 DALI_ASSERT_ALWAYS(path.size() > 4 && "Path is invalid.");
91 // Increase the reference count focely to avoid application mistake.
96 DALI_ASSERT_ALWAYS(source && "Source is NULL.");
99 SetupResources( size, clearColor, source );
102 Dali::Capture::CaptureFinishedSignalType& Capture::FinishedSignal()
104 return mFinishedSignal;
107 void Capture::Initialize()
111 void Capture::CreateSurface( const Vector2& size )
113 DALI_ASSERT_ALWAYS(!mTbmSurface && "mTbmSurface is already created.");
115 mTbmSurface = tbm_surface_create( size.width, size.height, TBM_FORMAT_RGBA8888 );
118 void Capture::DeleteSurface()
120 DALI_ASSERT_ALWAYS(mTbmSurface && "mTbmSurface is empty.");
122 tbm_surface_destroy( mTbmSurface );
126 void Capture::ClearSurface( const Vector2& size )
128 DALI_ASSERT_ALWAYS(mTbmSurface && "mTbmSurface is empty.");
130 tbm_surface_info_s surface_info;
132 if( tbm_surface_map( mTbmSurface, TBM_SURF_OPTION_WRITE, &surface_info ) == TBM_SURFACE_ERROR_NONE )
134 //DALI_ASSERT_ALWAYS(surface_info.bpp == 32 && "unsupported tbm format");
136 unsigned char* ptr = surface_info.planes[0].ptr;
137 memset( ptr, 0, surface_info.size ); // TODO: support color
139 if( tbm_surface_unmap( mTbmSurface ) != TBM_SURFACE_ERROR_NONE )
141 DALI_LOG_ERROR( "Fail to unmap tbm_surface\n" );
146 DALI_ASSERT_ALWAYS(0 && "tbm_surface_map failed");
150 bool Capture::IsSurfaceCreated()
152 return mTbmSurface != 0;
155 void Capture::CreateNativeImageSource()
157 Dali::Adaptor& adaptor = Dali::Adaptor::Get();
159 DALI_ASSERT_ALWAYS(adaptor.IsAvailable() && "Dali::Adaptor is not available.");
161 DALI_ASSERT_ALWAYS(mTbmSurface && "mTbmSurface is empty.");
163 DALI_ASSERT_ALWAYS(!mNativeImageSourcePtr && "NativeImageSource is already created.");
165 // create the NativeImageSource object with our surface
166 mNativeImageSourcePtr = Dali::NativeImageSource::New( mTbmSurface );
169 void Capture::DeleteNativeImageSource()
171 DALI_ASSERT_ALWAYS(mNativeImageSourcePtr && "mNativeImageSource is NULL.");
173 mNativeImageSourcePtr.Reset();
176 bool Capture::IsNativeImageSourceCreated()
178 return mNativeImageSourcePtr;
181 void Capture::CreateFrameBuffer()
183 DALI_ASSERT_ALWAYS(mNativeImageSourcePtr && "NativeImageSource is NULL.");
185 DALI_ASSERT_ALWAYS(!mFrameBuffer && "FrameBuffer is already created.");
187 mNativeTexture = Dali::Texture::New( *mNativeImageSourcePtr );
189 // Create a FrameBuffer object with no default attachments.
190 mFrameBuffer = Dali::FrameBuffer::New( mNativeTexture.GetWidth(), mNativeTexture.GetHeight(), Dali::FrameBuffer::Attachment::NONE );
191 // Add a color attachment to the FrameBuffer object.
192 mFrameBuffer.AttachColorTexture( mNativeTexture );
195 void Capture::DeleteFrameBuffer()
197 DALI_ASSERT_ALWAYS(mFrameBuffer && "FrameBuffer is NULL.");
199 mFrameBuffer.Reset();
200 mNativeTexture.Reset();
203 bool Capture::IsFrameBufferCreated()
208 void Capture::SetupRenderTask( Dali::Actor source, const Dali::Vector4& clearColor )
210 DALI_ASSERT_ALWAYS(source && "Source is empty.");
214 // Check the original parent about source.
215 mParent = mSource.GetParent();
217 Dali::Stage stage = Dali::Stage::GetCurrent();
218 Dali::Size stageSize = stage.GetSize();
220 // Add to stage for rendering the source. If source isn't on the stage then it never be rendered.
221 stage.Add( mSource );
225 mCameraActor = Dali::CameraActor::New( stageSize );
226 mCameraActor.SetParentOrigin( ParentOrigin::CENTER );
227 mCameraActor.SetAnchorPoint( AnchorPoint::CENTER );
230 stage.Add( mCameraActor );
232 DALI_ASSERT_ALWAYS(mFrameBuffer && "Framebuffer is NULL.");
234 DALI_ASSERT_ALWAYS(!mRenderTask && "RenderTask is already created.");
236 Dali::RenderTaskList taskList = stage.GetRenderTaskList();
237 mRenderTask = taskList.CreateTask();
238 mRenderTask.SetRefreshRate( Dali::RenderTask::REFRESH_ONCE );
239 mRenderTask.SetSourceActor( source );
240 mRenderTask.SetCameraActor( mCameraActor );
241 mRenderTask.SetScreenToFrameBufferFunction( Dali::RenderTask::FULLSCREEN_FRAMEBUFFER_FUNCTION );
242 mRenderTask.SetFrameBuffer( mFrameBuffer );
243 mRenderTask.SetClearColor( clearColor );
244 mRenderTask.SetClearEnabled( true );
245 mRenderTask.SetProperty( Dali::RenderTask::Property::REQUIRES_SYNC, true );
246 mRenderTask.FinishedSignal().Connect( this, &Capture::OnRenderFinished );
247 mRenderTask.GetCameraActor().SetInvertYAxis( true );
249 mTimer = Dali::Timer::New( TIME_OUT_DURATION );
250 mTimer.TickSignal().Connect( this, &Capture::OnTimeOut );
254 void Capture::UnsetRenderTask()
256 DALI_ASSERT_ALWAYS(mCameraActor && "CameraActor is NULL.");
260 // Restore the parent of source.
261 mParent.Add( mSource );
273 mCameraActor.Unparent();
274 mCameraActor.Reset();
276 DALI_ASSERT_ALWAYS(mRenderTask && "RenderTask is NULL.");
278 Dali::RenderTaskList taskList = Dali::Stage::GetCurrent().GetRenderTaskList();
279 Dali::RenderTask firstTask = taskList.GetTask( 0u );
281 // Stop rendering via frame-buffers as empty handle is used to clear target
282 firstTask.SetFrameBuffer( Dali::FrameBuffer() );
284 taskList.RemoveTask( mRenderTask );
288 bool Capture::IsRenderTaskSetup()
290 return mCameraActor && mRenderTask;
293 void Capture::SetupResources( const Dali::Vector2& size, const Dali::Vector4& clearColor, Dali::Actor source )
295 CreateSurface( size );
296 ClearSurface( size );
298 CreateNativeImageSource();
302 SetupRenderTask( source, clearColor );
305 void Capture::UnsetResources()
307 if( IsRenderTaskSetup() )
312 if( IsFrameBufferCreated() )
317 if( IsNativeImageSourceCreated() )
319 DeleteNativeImageSource();
322 if( IsSurfaceCreated() )
328 void Capture::OnRenderFinished( Dali::RenderTask& task )
330 Dali::Capture::FinishState state = Dali::Capture::FinishState::SUCCEEDED;
336 state = Dali::Capture::FinishState::FAILED;
337 DALI_LOG_ERROR("Fail to Capture mTbmSurface[%p] Path[%s]", mTbmSurface, mPath.c_str());
340 Dali::Capture handle( this );
341 mFinishedSignal.Emit( handle, state );
345 // Decrease the reference count forcely. It is increased at Start().
349 bool Capture::OnTimeOut()
351 Dali::Capture::FinishState state = Dali::Capture::FinishState::FAILED;
353 Dali::Capture handle( this );
354 mFinishedSignal.Emit( handle, state );
358 // Decrease the reference count forcely. It is increased at Start().
366 DALI_ASSERT_ALWAYS(mNativeImageSourcePtr && "mNativeImageSourcePtr is NULL");
368 return mNativeImageSourcePtr->EncodeToFile( mPath );
371 } // End of namespace Adaptor
373 } // End of namespace Internal
375 } // End of namespace Dali