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/dali.h>
20 #include <dali/devel-api/images/native-image-interface-extension.h>
21 #include <dali-toolkit/dali-toolkit.h>
25 #include "shared/utility.h"
28 using namespace Toolkit;
33 const float BUTTON_HEIGHT = 100.0f;
34 const float BUTTON_COUNT = 5.0f;
36 const std::string JPG_FILENAME = DEMO_IMAGE_DIR "gallery-medium-4.jpg";
37 const std::string CAPTURE_FILENAME = "/tmp/native-image-capture.png";
40 * @brief Creates a shader used to render a native image
41 * @param[in] nativeImageInterface The native image interface
42 * @return A shader to render the native image
44 Shader CreateShader( NativeImageInterface& nativeImageInterface )
46 static const char* DEFAULT_SAMPLER_TYPENAME = "sampler2D";
48 static const char* VERTEX_SHADER_TEXTURE = DALI_COMPOSE_SHADER(
49 attribute mediump vec2 aPosition;\n
50 attribute mediump vec2 aTexCoord;\n
51 uniform mediump mat4 uMvpMatrix;\n
52 uniform mediump vec3 uSize;\n
53 varying mediump vec2 vTexCoord;\n
56 vec4 position = vec4(aPosition,0.0,1.0)*vec4(uSize,1.0);\n
57 gl_Position = uMvpMatrix * position;\n
58 vTexCoord = aTexCoord;\n
62 static const char* FRAGMENT_SHADER_TEXTURE = DALI_COMPOSE_SHADER(
63 uniform lowp vec4 uColor;\n
64 uniform sampler2D sTexture;\n
65 varying mediump vec2 vTexCoord;\n
69 gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor;\n
73 NativeImageInterface::Extension* extension( nativeImageInterface.GetExtension() );
76 std::string fragmentShader;
78 //Get custom fragment shader prefix
79 const char* fragmentPreFix = extension->GetCustomFragmentPreFix();
82 fragmentShader = fragmentPreFix;
83 fragmentShader += FRAGMENT_SHADER_TEXTURE;
87 fragmentShader = FRAGMENT_SHADER_TEXTURE;
90 //Get custom sampler type name
91 const char* customSamplerTypename = extension->GetCustomSamplerTypename();
92 if( customSamplerTypename )
94 fragmentShader.replace( fragmentShader.find( DEFAULT_SAMPLER_TYPENAME ), strlen(DEFAULT_SAMPLER_TYPENAME), customSamplerTypename );
97 return Shader::New( VERTEX_SHADER_TEXTURE, fragmentShader );
101 return Shader::New( VERTEX_SHADER_TEXTURE, FRAGMENT_SHADER_TEXTURE );
107 // This example shows how to create and use a NativeImageSource as the target of the render task.
109 class NativeImageSourceController : public ConnectionTracker
113 NativeImageSourceController( Application& application )
114 : mApplication( application ),
115 mRefreshAlways( true )
117 // Connect to the Application's Init signal
118 mApplication.InitSignal().Connect( this, &NativeImageSourceController::Create );
121 ~NativeImageSourceController()
123 // Nothing to do here;
126 // The Init signal is received once (only) during the Application lifetime
127 void Create( Application& application )
129 // Get a handle to the stage
130 Stage stage = Stage::GetCurrent();
131 stage.SetBackgroundColor( Color::WHITE );
133 stage.KeyEventSignal().Connect(this, &NativeImageSourceController::OnKeyEvent);
137 CreateContentAreas();
140 void CreateButtonArea()
142 Stage stage = Stage::GetCurrent();
143 Vector2 stageSize = stage.GetSize();
145 mButtonArea = Layer::New();
146 mButtonArea.SetProperty( Actor::Property::SIZE, Vector2( stageSize.x, BUTTON_HEIGHT ) );
147 mButtonArea.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_CENTER );
148 mButtonArea.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_CENTER );
149 stage.Add( mButtonArea );
151 mButtonShow = PushButton::New();
152 mButtonShow.SetProperty( Button::Property::TOGGLABLE, true );
153 mButtonShow.SetProperty( Toolkit::Button::Property::LABEL, "SHOW" );
154 mButtonShow.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT );
155 mButtonShow.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
156 mButtonShow.SetProperty( Actor::Property::SIZE, Vector2( stageSize.x / BUTTON_COUNT, BUTTON_HEIGHT ) );
157 mButtonShow.ClickedSignal().Connect( this, &NativeImageSourceController::OnButtonSelected );
158 mButtonArea.Add( mButtonShow );
160 mButtonRefreshAlways = PushButton::New();
161 mButtonRefreshAlways.SetProperty( Button::Property::TOGGLABLE, true );
162 mButtonRefreshAlways.SetProperty( Toolkit::Button::Property::LABEL, "ALWAYS" );
163 mButtonRefreshAlways.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT );
164 mButtonRefreshAlways.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
165 mButtonRefreshAlways.SetProperty( Actor::Property::SIZE, Vector2( stageSize.x / BUTTON_COUNT, BUTTON_HEIGHT ) );
166 mButtonRefreshAlways.SetProperty( Actor::Property::POSITION, Vector2( (stageSize.x / BUTTON_COUNT)*1.0f, 0.0f ));
167 mButtonRefreshAlways.StateChangedSignal().Connect( this, &NativeImageSourceController::OnButtonSelected );
168 mButtonArea.Add( mButtonRefreshAlways );
170 mButtonRefreshOnce = PushButton::New();
171 mButtonRefreshOnce.SetProperty( Toolkit::Button::Property::LABEL, "ONCE" );
172 mButtonRefreshOnce.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT );
173 mButtonRefreshOnce.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
174 mButtonRefreshOnce.SetProperty( Actor::Property::SIZE, Vector2( stageSize.x / BUTTON_COUNT, BUTTON_HEIGHT ) );
175 mButtonRefreshOnce.SetProperty( Actor::Property::POSITION, Vector2( (stageSize.x / BUTTON_COUNT)*2.0f, 0.0f ));
176 mButtonRefreshOnce.ClickedSignal().Connect( this, &NativeImageSourceController::OnButtonSelected );
177 mButtonArea.Add( mButtonRefreshOnce );
179 mButtonCapture = PushButton::New();
180 mButtonCapture.SetProperty( Toolkit::Button::Property::LABEL, "CAPTURE" );
181 mButtonCapture.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT );
182 mButtonCapture.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
183 mButtonCapture.SetProperty( Actor::Property::SIZE, Vector2( stageSize.x / BUTTON_COUNT, BUTTON_HEIGHT ) );
184 mButtonCapture.SetProperty( Actor::Property::POSITION, Vector2( (stageSize.x / BUTTON_COUNT)*3.0f, 0.0f ));
185 mButtonCapture.ClickedSignal().Connect( this, &NativeImageSourceController::OnButtonSelected );
186 mButtonArea.Add( mButtonCapture );
188 mButtonReset = PushButton::New();
189 mButtonReset.SetProperty( Toolkit::Button::Property::LABEL, "RESET" );
190 mButtonReset.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT );
191 mButtonReset.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
192 mButtonReset.SetProperty( Actor::Property::SIZE, Vector2( stageSize.x / BUTTON_COUNT, BUTTON_HEIGHT ) );
193 mButtonReset.SetProperty( Actor::Property::POSITION, Vector2( (stageSize.x / BUTTON_COUNT)*4.0f, 0.0f ));
194 mButtonReset.ClickedSignal().Connect( this, &NativeImageSourceController::OnButtonSelected );
195 mButtonArea.Add( mButtonReset );
198 void CreateContentAreas()
200 Stage stage = Stage::GetCurrent();
201 Vector2 stageSize = stage.GetSize();
203 float contentHeight( (stageSize.y - BUTTON_HEIGHT)/2.0f );
205 mTopContentArea = Actor::New();
206 mTopContentArea.SetProperty( Actor::Property::SIZE, Vector2( stageSize.x, contentHeight ) );
207 mTopContentArea.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_CENTER );
208 mTopContentArea.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_CENTER );
209 mTopContentArea.SetProperty( Actor::Property::POSITION_Y, BUTTON_HEIGHT );
210 stage.Add( mTopContentArea );
212 mBottomContentArea = Actor::New();
213 mBottomContentArea.SetProperty( Actor::Property::SIZE, Vector2( stageSize.x, contentHeight ) );
214 mBottomContentArea.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::BOTTOM_CENTER );
215 mBottomContentArea.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::BOTTOM_CENTER );
216 stage.Add( mBottomContentArea );
218 mSourceActor = ImageView::New(JPG_FILENAME);
219 mSourceActor.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
220 mSourceActor.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER );
221 mTopContentArea.Add( mSourceActor );
223 Animation animation = Animation::New(2.f);
224 Degree relativeRotationDegrees(90.0f);
225 Radian relativeRotationRadians(relativeRotationDegrees);
226 animation.AnimateTo( Property( mSourceActor, Actor::Property::ORIENTATION ), Quaternion( relativeRotationRadians, Vector3::ZAXIS ), AlphaFunction::LINEAR, TimePeriod(0.f, 0.5f));
227 animation.AnimateBy( Property( mSourceActor, Actor::Property::ORIENTATION ), Quaternion( relativeRotationRadians, Vector3::ZAXIS ), AlphaFunction::LINEAR, TimePeriod(0.5f, 0.5f));
228 animation.AnimateBy( Property( mSourceActor, Actor::Property::ORIENTATION ), Quaternion( relativeRotationRadians, Vector3::ZAXIS ), AlphaFunction::LINEAR, TimePeriod(1.f, 0.5f));
229 animation.AnimateBy( Property( mSourceActor, Actor::Property::ORIENTATION ), Quaternion( relativeRotationRadians, Vector3::ZAXIS ), AlphaFunction::LINEAR, TimePeriod(1.5f, 0.5f));
230 animation.SetLooping(true);
233 TextLabel textLabel1 = TextLabel::New( "Image" );
234 textLabel1.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::BOTTOM_CENTER );
235 textLabel1.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::BOTTOM_CENTER );
236 mTopContentArea.Add( textLabel1 );
238 // Wait until button press before creating mOffscreenRenderTask
240 TextLabel textLabel2 = TextLabel::New( "Native Image" );
241 textLabel2.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::BOTTOM_CENTER );
242 textLabel2.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::BOTTOM_CENTER );
243 mBottomContentArea.Add( textLabel2 );
246 void SetupNativeImage()
248 if( ! mOffscreenRenderTask )
250 Stage stage = Stage::GetCurrent();
251 Vector2 stageSize = stage.GetSize();
253 float contentHeight( (stageSize.y - BUTTON_HEIGHT)/2.0f );
254 Vector2 imageSize( stageSize.x, contentHeight );
256 mNativeImageSourcePtr = NativeImageSource::New( imageSize.width, imageSize.height, NativeImageSource::COLOR_DEPTH_DEFAULT );
257 mNativeTexture = Texture::New( *mNativeImageSourcePtr );
259 mFrameBuffer = FrameBuffer::New( mNativeTexture.GetWidth(), mNativeTexture.GetHeight(), FrameBuffer::Attachment::NONE );
260 mFrameBuffer.AttachColorTexture( mNativeTexture );
262 mCameraActor = CameraActor::New( imageSize );
263 mCameraActor.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
264 mCameraActor.SetProperty( Actor::Property::PARENT_ORIGIN, AnchorPoint::CENTER );
265 mTopContentArea.Add( mCameraActor );
267 RenderTaskList taskList = stage.GetRenderTaskList();
268 mOffscreenRenderTask = taskList.CreateTask();
269 mOffscreenRenderTask.SetSourceActor( mSourceActor );
270 mOffscreenRenderTask.SetClearColor( Color::WHITE );
271 mOffscreenRenderTask.SetClearEnabled( true );
272 mOffscreenRenderTask.SetCameraActor( mCameraActor );
273 mOffscreenRenderTask.GetCameraActor().SetInvertYAxis( true );
274 mOffscreenRenderTask.SetFrameBuffer( mFrameBuffer );
279 mOffscreenRenderTask.SetRefreshRate( RenderTask::REFRESH_ALWAYS );
283 mOffscreenRenderTask.SetRefreshRate( RenderTask::REFRESH_ONCE );
287 void SetupDisplayActor( bool show )
291 if( ! mDisplayActor )
293 // Make sure we have something to display
296 mDisplayActor = Actor::New();
297 mDisplayActor.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
298 mDisplayActor.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER );
300 Geometry geometry = DemoHelper::CreateTexturedQuad();
302 Shader shader = CreateShader( *mNativeImageSourcePtr );
304 Renderer renderer = Renderer::New( geometry, shader );
306 TextureSet textureSet = TextureSet::New();
307 textureSet.SetTexture( 0u, mNativeTexture );
308 renderer.SetTextures( textureSet );
310 mDisplayActor.AddRenderer( renderer );
311 mDisplayActor.SetProperty( Actor::Property::SIZE, Vector2( mNativeTexture.GetWidth(), mNativeTexture.GetHeight() ) );
313 mBottomContentArea.Add( mDisplayActor );
318 UnparentAndReset( mDisplayActor );
324 mRefreshAlways = false;
327 mOffscreenRenderTask.FinishedSignal().Connect( this, &NativeImageSourceController::DoCapture );
330 void DoCapture(RenderTask& task)
332 task.FinishedSignal().Disconnect( this, &NativeImageSourceController::DoCapture );
334 mNativeImageSourcePtr->EncodeToFile( CAPTURE_FILENAME );
339 SetupDisplayActor( false );
341 Stage stage = Stage::GetCurrent();
342 RenderTaskList taskList = stage.GetRenderTaskList();
343 taskList.RemoveTask( mOffscreenRenderTask );
344 mOffscreenRenderTask.Reset();
345 mCameraActor.Reset();
347 mFrameBuffer.Reset();
348 mNativeTexture.Reset();
349 mNativeImageSourcePtr.Reset();
352 bool OnButtonSelected( Toolkit::Button button )
354 Toolkit::PushButton pushButton = Toolkit::PushButton::DownCast( button );
356 if( pushButton == mButtonShow )
358 bool isSelected = mButtonShow.GetProperty( Toolkit::Button::Property::SELECTED ).Get<bool>();
360 SetupDisplayActor( isSelected );
362 else if( pushButton == mButtonRefreshAlways )
364 bool isSelected = mButtonRefreshAlways.GetProperty( Toolkit::Button::Property::SELECTED ).Get<bool>();
366 mRefreshAlways = isSelected;
369 else if( pushButton == mButtonRefreshOnce )
371 bool isSelected = mButtonRefreshAlways.GetProperty( Toolkit::Button::Property::SELECTED ).Get<bool>();
375 mButtonRefreshAlways.SetProperty( Button::Property::SELECTED, false );
378 mRefreshAlways = false;
381 else if( pushButton == mButtonCapture )
385 else if( pushButton == mButtonReset )
393 void OnKeyEvent(const KeyEvent& event)
395 if(event.state == KeyEvent::Down)
397 if( IsKey( event, Dali::DALI_KEY_ESCAPE) || IsKey( event, Dali::DALI_KEY_BACK) )
406 Application& mApplication;
409 Actor mTopContentArea;
410 Actor mBottomContentArea;
412 PushButton mButtonShow;
413 PushButton mButtonRefreshAlways;
414 PushButton mButtonRefreshOnce;
415 PushButton mButtonCapture;
416 PushButton mButtonReset;
420 NativeImageSourcePtr mNativeImageSourcePtr;
421 Texture mNativeTexture;
422 FrameBuffer mFrameBuffer;
424 RenderTask mOffscreenRenderTask;
425 CameraActor mCameraActor;
432 int DALI_EXPORT_API main( int argc, char **argv )
434 Application application = Application::New( &argc, &argv );
435 NativeImageSourceController test( application );
436 application.MainLoop();