2 * Copyright (c) 2017 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/public-api/rendering/renderer.h>
22 #include <dali/public-api/rendering/frame-buffer.h>
23 #include <dali-toolkit/dali-toolkit.h>
27 #include "shared/utility.h"
30 using namespace Toolkit;
35 const float BUTTON_HEIGHT = 100.0f;
36 const float BUTTON_COUNT = 5.0f;
38 const std::string JPG_FILENAME = DEMO_IMAGE_DIR "gallery-medium-4.jpg";
39 const std::string CAPTURE_FILENAME = "/tmp/native-image-capture.png";
42 * @brief Creates a shader used to render a native image
43 * @param[in] nativeImageInterface The native image interface
44 * @return A shader to render the native image
46 Shader CreateShader( NativeImageInterface& nativeImageInterface )
48 static const char* DEFAULT_SAMPLER_TYPENAME = "sampler2D";
50 static const char* VERTEX_SHADER_TEXTURE = DALI_COMPOSE_SHADER(
51 attribute mediump vec2 aPosition;\n
52 attribute mediump vec2 aTexCoord;\n
53 uniform mediump mat4 uMvpMatrix;\n
54 uniform mediump vec3 uSize;\n
55 varying mediump vec2 vTexCoord;\n
58 vec4 position = vec4(aPosition,0.0,1.0)*vec4(uSize,1.0);\n
59 gl_Position = uMvpMatrix * position;\n
60 vTexCoord = aTexCoord;\n
64 static const char* FRAGMENT_SHADER_TEXTURE = DALI_COMPOSE_SHADER(
65 uniform lowp vec4 uColor;\n
66 uniform sampler2D sTexture;\n
67 varying mediump vec2 vTexCoord;\n
71 gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor;\n
75 NativeImageInterface::Extension* extension( nativeImageInterface.GetExtension() );
78 std::string fragmentShader;
80 //Get custom fragment shader prefix
81 const char* fragmentPreFix = extension->GetCustomFragmentPreFix();
84 fragmentShader = fragmentPreFix;
85 fragmentShader += FRAGMENT_SHADER_TEXTURE;
89 fragmentShader = FRAGMENT_SHADER_TEXTURE;
92 //Get custom sampler type name
93 const char* customSamplerTypename = extension->GetCustomSamplerTypename();
94 if( customSamplerTypename )
96 fragmentShader.replace( fragmentShader.find( DEFAULT_SAMPLER_TYPENAME ), strlen(DEFAULT_SAMPLER_TYPENAME), customSamplerTypename );
99 return Shader::New( VERTEX_SHADER_TEXTURE, fragmentShader );
103 return Shader::New( VERTEX_SHADER_TEXTURE, FRAGMENT_SHADER_TEXTURE );
109 // This example shows how to create and use a NativeImageSource as the target of the render task.
111 class NativeImageSourceController : public ConnectionTracker
115 NativeImageSourceController( Application& application )
116 : mApplication( application ),
117 mRefreshAlways( true )
119 // Connect to the Application's Init signal
120 mApplication.InitSignal().Connect( this, &NativeImageSourceController::Create );
123 ~NativeImageSourceController()
125 // Nothing to do here;
128 // The Init signal is received once (only) during the Application lifetime
129 void Create( Application& application )
131 // Get a handle to the stage
132 Stage stage = Stage::GetCurrent();
133 stage.SetBackgroundColor( Color::WHITE );
135 // Hide the indicator bar
136 application.GetWindow().ShowIndicator( Dali::Window::INVISIBLE );
138 stage.KeyEventSignal().Connect(this, &NativeImageSourceController::OnKeyEvent);
142 CreateContentAreas();
145 void CreateButtonArea()
147 Stage stage = Stage::GetCurrent();
148 Vector2 stageSize = stage.GetSize();
150 mButtonArea = Layer::New();
151 mButtonArea.SetSize( stageSize.x, BUTTON_HEIGHT );
152 mButtonArea.SetParentOrigin( ParentOrigin::TOP_CENTER );
153 mButtonArea.SetAnchorPoint( AnchorPoint::TOP_CENTER );
154 stage.Add( mButtonArea );
156 mButtonShow = PushButton::New();
157 mButtonShow.SetProperty( Button::Property::TOGGLABLE, true );
158 mButtonShow.SetProperty( Toolkit::Button::Property::LABEL, "SHOW" );
159 mButtonShow.SetParentOrigin( ParentOrigin::TOP_LEFT );
160 mButtonShow.SetAnchorPoint( AnchorPoint::TOP_LEFT );
161 mButtonShow.SetSize( stageSize.x / BUTTON_COUNT, BUTTON_HEIGHT );
162 mButtonShow.ClickedSignal().Connect( this, &NativeImageSourceController::OnButtonSelected );
163 mButtonArea.Add( mButtonShow );
165 mButtonRefreshAlways = PushButton::New();
166 mButtonRefreshAlways.SetProperty( Button::Property::TOGGLABLE, true );
167 mButtonRefreshAlways.SetProperty( Toolkit::Button::Property::LABEL, "ALWAYS" );
168 mButtonRefreshAlways.SetParentOrigin( ParentOrigin::TOP_LEFT );
169 mButtonRefreshAlways.SetAnchorPoint( AnchorPoint::TOP_LEFT );
170 mButtonRefreshAlways.SetSize( stageSize.x / BUTTON_COUNT, BUTTON_HEIGHT );
171 mButtonRefreshAlways.SetPosition( (stageSize.x / BUTTON_COUNT)*1.0f, 0.0f );
172 mButtonRefreshAlways.StateChangedSignal().Connect( this, &NativeImageSourceController::OnButtonSelected );
173 mButtonArea.Add( mButtonRefreshAlways );
175 mButtonRefreshOnce = PushButton::New();
176 mButtonRefreshOnce.SetProperty( Toolkit::Button::Property::LABEL, "ONCE" );
177 mButtonRefreshOnce.SetParentOrigin( ParentOrigin::TOP_LEFT );
178 mButtonRefreshOnce.SetAnchorPoint( AnchorPoint::TOP_LEFT );
179 mButtonRefreshOnce.SetSize( stageSize.x / BUTTON_COUNT, BUTTON_HEIGHT );
180 mButtonRefreshOnce.SetPosition( (stageSize.x / BUTTON_COUNT)*2.0f, 0.0f );
181 mButtonRefreshOnce.ClickedSignal().Connect( this, &NativeImageSourceController::OnButtonSelected );
182 mButtonArea.Add( mButtonRefreshOnce );
184 mButtonCapture = PushButton::New();
185 mButtonCapture.SetProperty( Toolkit::Button::Property::LABEL, "CAPTURE" );
186 mButtonCapture.SetParentOrigin( ParentOrigin::TOP_LEFT );
187 mButtonCapture.SetAnchorPoint( AnchorPoint::TOP_LEFT );
188 mButtonCapture.SetSize( stageSize.x / BUTTON_COUNT, BUTTON_HEIGHT );
189 mButtonCapture.SetPosition( (stageSize.x / BUTTON_COUNT)*3.0f, 0.0f );
190 mButtonCapture.ClickedSignal().Connect( this, &NativeImageSourceController::OnButtonSelected );
191 mButtonArea.Add( mButtonCapture );
193 mButtonReset = PushButton::New();
194 mButtonReset.SetProperty( Toolkit::Button::Property::LABEL, "RESET" );
195 mButtonReset.SetParentOrigin( ParentOrigin::TOP_LEFT );
196 mButtonReset.SetAnchorPoint( AnchorPoint::TOP_LEFT );
197 mButtonReset.SetSize( stageSize.x / BUTTON_COUNT, BUTTON_HEIGHT );
198 mButtonReset.SetPosition( (stageSize.x / BUTTON_COUNT)*4.0f, 0.0f );
199 mButtonReset.ClickedSignal().Connect( this, &NativeImageSourceController::OnButtonSelected );
200 mButtonArea.Add( mButtonReset );
203 void CreateContentAreas()
205 Stage stage = Stage::GetCurrent();
206 Vector2 stageSize = stage.GetSize();
208 float contentHeight( (stageSize.y - BUTTON_HEIGHT)/2.0f );
210 mTopContentArea = Actor::New();
211 mTopContentArea.SetSize( stageSize.x, contentHeight );
212 mTopContentArea.SetParentOrigin( ParentOrigin::TOP_CENTER );
213 mTopContentArea.SetAnchorPoint( AnchorPoint::TOP_CENTER );
214 mTopContentArea.SetY( BUTTON_HEIGHT );
215 stage.Add( mTopContentArea );
217 mBottomContentArea = Actor::New();
218 mBottomContentArea.SetSize( stageSize.x, contentHeight );
219 mBottomContentArea.SetParentOrigin( ParentOrigin::BOTTOM_CENTER );
220 mBottomContentArea.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
221 stage.Add( mBottomContentArea );
223 mSourceActor = ImageView::New(JPG_FILENAME);
224 mSourceActor.SetParentOrigin( ParentOrigin::CENTER);
225 mSourceActor.SetAnchorPoint( AnchorPoint::CENTER );
226 mTopContentArea.Add( mSourceActor );
228 Animation animation = Animation::New(2.f);
229 Degree relativeRotationDegrees(90.0f);
230 Radian relativeRotationRadians(relativeRotationDegrees);
231 animation.AnimateTo( Property( mSourceActor, Actor::Property::ORIENTATION ), Quaternion( relativeRotationRadians, Vector3::ZAXIS ), AlphaFunction::LINEAR, TimePeriod(0.f, 0.5f));
232 animation.AnimateBy( Property( mSourceActor, Actor::Property::ORIENTATION ), Quaternion( relativeRotationRadians, Vector3::ZAXIS ), AlphaFunction::LINEAR, TimePeriod(0.5f, 0.5f));
233 animation.AnimateBy( Property( mSourceActor, Actor::Property::ORIENTATION ), Quaternion( relativeRotationRadians, Vector3::ZAXIS ), AlphaFunction::LINEAR, TimePeriod(1.f, 0.5f));
234 animation.AnimateBy( Property( mSourceActor, Actor::Property::ORIENTATION ), Quaternion( relativeRotationRadians, Vector3::ZAXIS ), AlphaFunction::LINEAR, TimePeriod(1.5f, 0.5f));
235 animation.SetLooping(true);
238 TextLabel textLabel1 = TextLabel::New( "Image" );
239 textLabel1.SetParentOrigin( ParentOrigin::BOTTOM_CENTER );
240 textLabel1.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
241 mTopContentArea.Add( textLabel1 );
243 // Wait until button press before creating mOffscreenRenderTask
245 TextLabel textLabel2 = TextLabel::New( "Native Image" );
246 textLabel2.SetParentOrigin( ParentOrigin::BOTTOM_CENTER );
247 textLabel2.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
248 mBottomContentArea.Add( textLabel2 );
251 void SetupNativeImage()
253 if( ! mOffscreenRenderTask )
255 Stage stage = Stage::GetCurrent();
256 Vector2 stageSize = stage.GetSize();
258 float contentHeight( (stageSize.y - BUTTON_HEIGHT)/2.0f );
259 Vector2 imageSize( stageSize.x, contentHeight );
261 mNativeImageSourcePtr = NativeImageSource::New( imageSize.width, imageSize.height, NativeImageSource::COLOR_DEPTH_DEFAULT );
262 mNativeTexture = Texture::New( *mNativeImageSourcePtr );
264 mFrameBuffer = FrameBuffer::New( mNativeTexture.GetWidth(), mNativeTexture.GetHeight(), FrameBuffer::Attachment::NONE );
265 mFrameBuffer.AttachColorTexture( mNativeTexture );
267 mCameraActor = CameraActor::New( imageSize );
268 mCameraActor.SetParentOrigin( ParentOrigin::CENTER );
269 mCameraActor.SetParentOrigin( AnchorPoint::CENTER );
270 mTopContentArea.Add( mCameraActor );
272 RenderTaskList taskList = stage.GetRenderTaskList();
273 mOffscreenRenderTask = taskList.CreateTask();
274 mOffscreenRenderTask.SetSourceActor( mSourceActor );
275 mOffscreenRenderTask.SetClearColor( Color::WHITE );
276 mOffscreenRenderTask.SetClearEnabled( true );
277 mOffscreenRenderTask.SetCameraActor( mCameraActor );
278 mOffscreenRenderTask.GetCameraActor().SetInvertYAxis( true );
279 mOffscreenRenderTask.SetFrameBuffer( mFrameBuffer );
284 mOffscreenRenderTask.SetRefreshRate( RenderTask::REFRESH_ALWAYS );
288 mOffscreenRenderTask.SetRefreshRate( RenderTask::REFRESH_ONCE );
292 void SetupDisplayActor( bool show )
296 if( ! mDisplayActor )
298 // Make sure we have something to display
301 mDisplayActor = Actor::New();
302 mDisplayActor.SetParentOrigin( ParentOrigin::CENTER );
303 mDisplayActor.SetAnchorPoint( AnchorPoint::CENTER );
305 Geometry geometry = DemoHelper::CreateTexturedQuad();
307 Shader shader = CreateShader( *mNativeImageSourcePtr );
309 Renderer renderer = Renderer::New( geometry, shader );
311 TextureSet textureSet = TextureSet::New();
312 textureSet.SetTexture( 0u, mNativeTexture );
313 renderer.SetTextures( textureSet );
315 mDisplayActor.AddRenderer( renderer );
316 mDisplayActor.SetSize( mNativeTexture.GetWidth(), mNativeTexture.GetHeight() );
318 mBottomContentArea.Add( mDisplayActor );
323 UnparentAndReset( mDisplayActor );
329 mRefreshAlways = false;
332 mOffscreenRenderTask.FinishedSignal().Connect( this, &NativeImageSourceController::DoCapture );
335 void DoCapture(RenderTask& task)
337 task.FinishedSignal().Disconnect( this, &NativeImageSourceController::DoCapture );
339 mNativeImageSourcePtr->EncodeToFile( CAPTURE_FILENAME );
344 SetupDisplayActor( false );
346 Stage stage = Stage::GetCurrent();
347 RenderTaskList taskList = stage.GetRenderTaskList();
348 taskList.RemoveTask( mOffscreenRenderTask );
349 mOffscreenRenderTask.Reset();
350 mCameraActor.Reset();
352 mFrameBuffer.Reset();
353 mNativeTexture.Reset();
354 mNativeImageSourcePtr.Reset();
357 bool OnButtonSelected( Toolkit::Button button )
359 Toolkit::PushButton pushButton = Toolkit::PushButton::DownCast( button );
361 if( pushButton == mButtonShow )
363 bool isSelected = mButtonShow.GetProperty( Toolkit::Button::Property::SELECTED ).Get<bool>();
365 SetupDisplayActor( isSelected );
367 else if( pushButton == mButtonRefreshAlways )
369 bool isSelected = mButtonRefreshAlways.GetProperty( Toolkit::Button::Property::SELECTED ).Get<bool>();
371 mRefreshAlways = isSelected;
374 else if( pushButton == mButtonRefreshOnce )
376 bool isSelected = mButtonRefreshAlways.GetProperty( Toolkit::Button::Property::SELECTED ).Get<bool>();
380 mButtonRefreshAlways.SetProperty( Button::Property::SELECTED, false );
383 mRefreshAlways = false;
386 else if( pushButton == mButtonCapture )
390 else if( pushButton == mButtonReset )
398 void OnKeyEvent(const KeyEvent& event)
400 if(event.state == KeyEvent::Down)
402 if( IsKey( event, Dali::DALI_KEY_ESCAPE) || IsKey( event, Dali::DALI_KEY_BACK) )
411 Application& mApplication;
414 Actor mTopContentArea;
415 Actor mBottomContentArea;
417 PushButton mButtonShow;
418 PushButton mButtonRefreshAlways;
419 PushButton mButtonRefreshOnce;
420 PushButton mButtonCapture;
421 PushButton mButtonReset;
425 NativeImageSourcePtr mNativeImageSourcePtr;
426 Texture mNativeTexture;
427 FrameBuffer mFrameBuffer;
429 RenderTask mOffscreenRenderTask;
430 CameraActor mCameraActor;
437 void RunTest( Application& application )
439 NativeImageSourceController test( application );
441 application.MainLoop();
444 // Entry point for Linux & Tizen applications
446 int DALI_EXPORT_API main( int argc, char **argv )
448 Application application = Application::New( &argc, &argv );
450 RunTest( application );