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>
28 #include <cynara-client.h>
31 #include <system_info.h>
38 unsigned int TIME_OUT_DURATION = 1000;
39 const int SMACK_LABEL_LENGTH = 255;
41 const char* const CYNARA_CHECK_FILE = "/proc/self/attr/current";
42 const char* const SCREEN_SHOT_PRIVILEGE = "http://tizen.org/privilege/screenshot";
57 mNativeImageSourcePtr( NULL ),
62 Capture::Capture( Dali::CameraActor cameraActor )
63 : mCameraActor( cameraActor ),
66 mNativeImageSourcePtr( NULL ),
75 CapturePtr Capture::New()
77 CapturePtr pWorker = new Capture();
79 if( pWorker->CheckPrivilege( SCREEN_SHOT_PRIVILEGE ) == false )
81 DALI_LOG_ERROR( "Capture privilege error: permission denied\n" );
88 CapturePtr Capture::New( Dali::CameraActor cameraActor )
90 CapturePtr pWorker = new Capture( cameraActor );
92 if( pWorker->CheckPrivilege( SCREEN_SHOT_PRIVILEGE ) == false )
94 DALI_LOG_ERROR( "Capture privilege error: permission denied\n" );
101 void Capture::Start( Dali::Actor source, const Dali::Vector2& size, const std::string &path, const Dali::Vector4& clearColor )
103 DALI_ASSERT_ALWAYS(path.size() > 4 && "Path is invalid.");
105 // Increase the reference count focely to avoid application mistake.
110 DALI_ASSERT_ALWAYS(source && "Source is NULL.");
113 SetupResources( size, clearColor, source );
116 Dali::Capture::CaptureFinishedSignalType& Capture::FinishedSignal()
118 return mFinishedSignal;
121 void Capture::CreateSurface( const Vector2& size )
123 DALI_ASSERT_ALWAYS(!mTbmSurface && "mTbmSurface is already created.");
125 mTbmSurface = tbm_surface_create( size.width, size.height, TBM_FORMAT_RGBA8888 );
128 void Capture::DeleteSurface()
130 DALI_ASSERT_ALWAYS(mTbmSurface && "mTbmSurface is empty.");
132 tbm_surface_destroy( mTbmSurface );
136 void Capture::ClearSurface( const Vector2& size )
138 DALI_ASSERT_ALWAYS(mTbmSurface && "mTbmSurface is empty.");
140 tbm_surface_info_s surface_info;
142 if( tbm_surface_map( mTbmSurface, TBM_SURF_OPTION_WRITE, &surface_info ) == TBM_SURFACE_ERROR_NONE )
144 //DALI_ASSERT_ALWAYS(surface_info.bpp == 32 && "unsupported tbm format");
146 unsigned char* ptr = surface_info.planes[0].ptr;
147 memset( ptr, 0, surface_info.size ); // TODO: support color
149 if( tbm_surface_unmap( mTbmSurface ) != TBM_SURFACE_ERROR_NONE )
151 DALI_LOG_ERROR( "Fail to unmap tbm_surface\n" );
156 DALI_ASSERT_ALWAYS(0 && "tbm_surface_map failed");
160 bool Capture::IsSurfaceCreated()
162 return mTbmSurface != 0;
165 void Capture::CreateNativeImageSource()
167 Dali::Adaptor& adaptor = Dali::Adaptor::Get();
169 DALI_ASSERT_ALWAYS(adaptor.IsAvailable() && "Dali::Adaptor is not available.");
171 DALI_ASSERT_ALWAYS(mTbmSurface && "mTbmSurface is empty.");
173 DALI_ASSERT_ALWAYS(!mNativeImageSourcePtr && "NativeImageSource is already created.");
175 // create the NativeImageSource object with our surface
176 mNativeImageSourcePtr = Dali::NativeImageSource::New( mTbmSurface );
179 void Capture::DeleteNativeImageSource()
181 DALI_ASSERT_ALWAYS(mNativeImageSourcePtr && "mNativeImageSource is NULL.");
183 mNativeImageSourcePtr.Reset();
186 bool Capture::IsNativeImageSourceCreated()
188 return mNativeImageSourcePtr;
191 void Capture::CreateFrameBuffer()
193 DALI_ASSERT_ALWAYS(mNativeImageSourcePtr && "NativeImageSource is NULL.");
195 DALI_ASSERT_ALWAYS(!mFrameBuffer && "FrameBuffer is already created.");
197 mNativeTexture = Dali::Texture::New( *mNativeImageSourcePtr );
199 // Create a FrameBuffer object with no default attachments.
200 mFrameBuffer = Dali::FrameBuffer::New( mNativeTexture.GetWidth(), mNativeTexture.GetHeight(), Dali::FrameBuffer::Attachment::NONE );
201 // Add a color attachment to the FrameBuffer object.
202 mFrameBuffer.AttachColorTexture( mNativeTexture );
205 void Capture::DeleteFrameBuffer()
207 DALI_ASSERT_ALWAYS(mFrameBuffer && "FrameBuffer is NULL.");
209 mFrameBuffer.Reset();
210 mNativeTexture.Reset();
213 bool Capture::IsFrameBufferCreated()
218 void Capture::SetupRenderTask( Dali::Actor source, const Dali::Vector4& clearColor )
220 DALI_ASSERT_ALWAYS(source && "Source is empty.");
224 // Check the original parent about source.
225 mParent = mSource.GetParent();
227 Dali::Stage stage = Dali::Stage::GetCurrent();
228 Dali::Size stageSize = stage.GetSize();
230 // Add to stage for rendering the source. If source isn't on the stage then it never be rendered.
231 stage.Add( mSource );
235 mCameraActor = Dali::CameraActor::New( stageSize );
236 mCameraActor.SetParentOrigin( ParentOrigin::CENTER );
237 mCameraActor.SetAnchorPoint( AnchorPoint::CENTER );
240 stage.Add( mCameraActor );
242 DALI_ASSERT_ALWAYS(mFrameBuffer && "Framebuffer is NULL.");
244 DALI_ASSERT_ALWAYS(!mRenderTask && "RenderTask is already created.");
246 Dali::RenderTaskList taskList = stage.GetRenderTaskList();
247 mRenderTask = taskList.CreateTask();
248 mRenderTask.SetRefreshRate( Dali::RenderTask::REFRESH_ONCE );
249 mRenderTask.SetSourceActor( source );
250 mRenderTask.SetCameraActor( mCameraActor );
251 mRenderTask.SetScreenToFrameBufferFunction( Dali::RenderTask::FULLSCREEN_FRAMEBUFFER_FUNCTION );
252 mRenderTask.SetFrameBuffer( mFrameBuffer );
253 mRenderTask.SetClearColor( clearColor );
254 mRenderTask.SetClearEnabled( true );
255 mRenderTask.SetProperty( Dali::RenderTask::Property::REQUIRES_SYNC, true );
256 mRenderTask.FinishedSignal().Connect( this, &Capture::OnRenderFinished );
257 mRenderTask.GetCameraActor().SetInvertYAxis( true );
259 mTimer = Dali::Timer::New( TIME_OUT_DURATION );
260 mTimer.TickSignal().Connect( this, &Capture::OnTimeOut );
264 void Capture::UnsetRenderTask()
266 DALI_ASSERT_ALWAYS(mCameraActor && "CameraActor is NULL.");
270 // Restore the parent of source.
271 mParent.Add( mSource );
283 mCameraActor.Unparent();
284 mCameraActor.Reset();
286 DALI_ASSERT_ALWAYS(mRenderTask && "RenderTask is NULL.");
288 Dali::RenderTaskList taskList = Dali::Stage::GetCurrent().GetRenderTaskList();
289 Dali::RenderTask firstTask = taskList.GetTask( 0u );
291 // Stop rendering via frame-buffers as empty handle is used to clear target
292 firstTask.SetFrameBuffer( Dali::FrameBuffer() );
294 taskList.RemoveTask( mRenderTask );
298 bool Capture::IsRenderTaskSetup()
300 return mCameraActor && mRenderTask;
303 void Capture::SetupResources( const Dali::Vector2& size, const Dali::Vector4& clearColor, Dali::Actor source )
305 CreateSurface( size );
306 ClearSurface( size );
308 CreateNativeImageSource();
312 SetupRenderTask( source, clearColor );
315 void Capture::UnsetResources()
317 if( IsRenderTaskSetup() )
322 if( IsFrameBufferCreated() )
327 if( IsNativeImageSourceCreated() )
329 DeleteNativeImageSource();
332 if( IsSurfaceCreated() )
338 void Capture::OnRenderFinished( Dali::RenderTask& task )
340 Dali::Capture::FinishState state = Dali::Capture::FinishState::SUCCEEDED;
346 state = Dali::Capture::FinishState::FAILED;
347 DALI_LOG_ERROR("Fail to Capture mTbmSurface[%p] Path[%s]", mTbmSurface, mPath.c_str());
350 Dali::Capture handle( this );
351 mFinishedSignal.Emit( handle, state );
355 // Decrease the reference count forcely. It is increased at Start().
359 bool Capture::OnTimeOut()
361 Dali::Capture::FinishState state = Dali::Capture::FinishState::FAILED;
363 Dali::Capture handle( this );
364 mFinishedSignal.Emit( handle, state );
368 // Decrease the reference count forcely. It is increased at Start().
376 DALI_ASSERT_ALWAYS(mNativeImageSourcePtr && "mNativeImageSourcePtr is NULL");
378 return mNativeImageSourcePtr->EncodeToFile( mPath );
381 bool Capture::CheckPrivilege( const char* privilege ) const
386 char subjectLabel[SMACK_LABEL_LENGTH + 1] = "";
387 char uid[10] = { 0, };
388 const char* clientSession = "";
390 ret = cynara_initialize( &cynara, NULL );
391 if( ret != CYNARA_API_SUCCESS )
396 fd = open( CYNARA_CHECK_FILE, O_RDONLY );
399 cynara_finish( cynara );
403 ret = read( fd, subjectLabel, SMACK_LABEL_LENGTH );
407 cynara_finish( cynara );
413 snprintf( uid, 10, "%d", getuid() );
415 ret = cynara_check( cynara, subjectLabel, clientSession, uid, privilege );
416 if( ret != CYNARA_API_ACCESS_ALLOWED )
418 cynara_finish( cynara );
422 cynara_finish( cynara );
427 } // End of namespace Adaptor
429 } // End of namespace Internal
431 } // End of namespace Dali