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-toolkit/dali-toolkit.h>
24 #include "shared/utility.h"
27 using namespace Toolkit;
32 const float BUTTON_HEIGHT = 100.0f;
33 const float BUTTON_COUNT = 5.0f;
35 const std::string JPG_FILENAME = DEMO_IMAGE_DIR "gallery-medium-4.jpg";
36 const std::string CAPTURE_FILENAME = "/tmp/native-image-capture.png";
39 * @brief Creates a shader used to render a native image
40 * @param[in] nativeImage The native image
41 * @return A shader to render the native image
43 Shader CreateShader( NativeImageInterface& nativeImage )
45 static const char* DEFAULT_SAMPLER_TYPENAME = "sampler2D";
47 static const char* VERTEX_SHADER_TEXTURE = DALI_COMPOSE_SHADER(
48 attribute mediump vec2 aPosition;\n
49 attribute mediump vec2 aTexCoord;\n
50 uniform mediump mat4 uMvpMatrix;\n
51 uniform mediump vec3 uSize;\n
52 varying mediump vec2 vTexCoord;\n
55 vec4 position = vec4(aPosition,0.0,1.0)*vec4(uSize,1.0);\n
56 gl_Position = uMvpMatrix * position;\n
57 vTexCoord = aTexCoord;\n
61 static const char* FRAGMENT_SHADER_TEXTURE = DALI_COMPOSE_SHADER(
62 uniform lowp vec4 uColor;\n
63 uniform sampler2D sTexture;\n
64 varying mediump vec2 vTexCoord;\n
68 gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor;\n
73 std::string fragmentShader;
75 //Get custom fragment shader prefix
76 const char* fragmentPrefix = nativeImage.GetCustomFragmentPrefix();
79 fragmentShader = fragmentPrefix;
80 fragmentShader += FRAGMENT_SHADER_TEXTURE;
84 fragmentShader = FRAGMENT_SHADER_TEXTURE;
87 //Get custom sampler type name
88 const char* customSamplerTypename = nativeImage.GetCustomSamplerTypename();
89 if( customSamplerTypename )
91 fragmentShader.replace( fragmentShader.find( DEFAULT_SAMPLER_TYPENAME ), strlen(DEFAULT_SAMPLER_TYPENAME), customSamplerTypename );
94 return Shader::New( VERTEX_SHADER_TEXTURE, fragmentShader );
99 // This example shows how to create and use a NativeImageSource as the target of the render task.
101 class NativeImageSourceController : public ConnectionTracker
105 NativeImageSourceController( Application& application )
106 : mApplication( application ),
107 mRefreshAlways( true )
109 // Connect to the Application's Init signal
110 mApplication.InitSignal().Connect( this, &NativeImageSourceController::Create );
113 ~NativeImageSourceController()
115 // Nothing to do here;
118 // The Init signal is received once (only) during the Application lifetime
119 void Create( Application& application )
121 // Get a handle to the window
122 Window window = application.GetWindow();
123 window.SetBackgroundColor( Color::WHITE );
125 window.KeyEventSignal().Connect(this, &NativeImageSourceController::OnKeyEvent);
129 CreateContentAreas();
132 void CreateButtonArea()
134 Window window = mApplication.GetWindow();
135 Vector2 windowSize = window.GetSize();
137 mButtonArea = Layer::New();
138 mButtonArea.SetProperty( Actor::Property::SIZE, Vector2( windowSize.x, BUTTON_HEIGHT ) );
139 mButtonArea.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_CENTER );
140 mButtonArea.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_CENTER );
141 window.Add( mButtonArea );
143 mButtonShow = PushButton::New();
144 mButtonShow.SetProperty( Button::Property::TOGGLABLE, true );
145 mButtonShow.SetProperty( Toolkit::Button::Property::LABEL, "SHOW" );
146 mButtonShow.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT );
147 mButtonShow.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
148 mButtonShow.SetProperty( Actor::Property::SIZE, Vector2( windowSize.x / BUTTON_COUNT, BUTTON_HEIGHT ) );
149 mButtonShow.ClickedSignal().Connect( this, &NativeImageSourceController::OnButtonSelected );
150 mButtonArea.Add( mButtonShow );
152 mButtonRefreshAlways = PushButton::New();
153 mButtonRefreshAlways.SetProperty( Button::Property::TOGGLABLE, true );
154 mButtonRefreshAlways.SetProperty( Toolkit::Button::Property::LABEL, "ALWAYS" );
155 mButtonRefreshAlways.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT );
156 mButtonRefreshAlways.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
157 mButtonRefreshAlways.SetProperty( Actor::Property::SIZE, Vector2( windowSize.x / BUTTON_COUNT, BUTTON_HEIGHT ) );
158 mButtonRefreshAlways.SetProperty( Actor::Property::POSITION, Vector2( (windowSize.x / BUTTON_COUNT)*1.0f, 0.0f ));
159 mButtonRefreshAlways.StateChangedSignal().Connect( this, &NativeImageSourceController::OnButtonSelected );
160 mButtonArea.Add( mButtonRefreshAlways );
162 mButtonRefreshOnce = PushButton::New();
163 mButtonRefreshOnce.SetProperty( Toolkit::Button::Property::LABEL, "ONCE" );
164 mButtonRefreshOnce.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT );
165 mButtonRefreshOnce.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
166 mButtonRefreshOnce.SetProperty( Actor::Property::SIZE, Vector2( windowSize.x / BUTTON_COUNT, BUTTON_HEIGHT ) );
167 mButtonRefreshOnce.SetProperty( Actor::Property::POSITION, Vector2( (windowSize.x / BUTTON_COUNT)*2.0f, 0.0f ));
168 mButtonRefreshOnce.ClickedSignal().Connect( this, &NativeImageSourceController::OnButtonSelected );
169 mButtonArea.Add( mButtonRefreshOnce );
171 mButtonCapture = PushButton::New();
172 mButtonCapture.SetProperty( Toolkit::Button::Property::LABEL, "CAPTURE" );
173 mButtonCapture.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT );
174 mButtonCapture.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
175 mButtonCapture.SetProperty( Actor::Property::SIZE, Vector2( windowSize.x / BUTTON_COUNT, BUTTON_HEIGHT ) );
176 mButtonCapture.SetProperty( Actor::Property::POSITION, Vector2( (windowSize.x / BUTTON_COUNT)*3.0f, 0.0f ));
177 mButtonCapture.ClickedSignal().Connect( this, &NativeImageSourceController::OnButtonSelected );
178 mButtonArea.Add( mButtonCapture );
180 mButtonReset = PushButton::New();
181 mButtonReset.SetProperty( Toolkit::Button::Property::LABEL, "RESET" );
182 mButtonReset.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT );
183 mButtonReset.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
184 mButtonReset.SetProperty( Actor::Property::SIZE, Vector2( windowSize.x / BUTTON_COUNT, BUTTON_HEIGHT ) );
185 mButtonReset.SetProperty( Actor::Property::POSITION, Vector2( (windowSize.x / BUTTON_COUNT)*4.0f, 0.0f ));
186 mButtonReset.ClickedSignal().Connect( this, &NativeImageSourceController::OnButtonSelected );
187 mButtonArea.Add( mButtonReset );
190 void CreateContentAreas()
192 Window window = mApplication.GetWindow();
193 Vector2 windowSize = window.GetSize();
195 float contentHeight( (windowSize.y - BUTTON_HEIGHT)/2.0f );
197 mTopContentArea = Actor::New();
198 mTopContentArea.SetProperty( Actor::Property::SIZE, Vector2( windowSize.x, contentHeight ) );
199 mTopContentArea.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_CENTER );
200 mTopContentArea.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_CENTER );
201 mTopContentArea.SetProperty( Actor::Property::POSITION_Y, BUTTON_HEIGHT );
202 window.Add( mTopContentArea );
204 mBottomContentArea = Actor::New();
205 mBottomContentArea.SetProperty( Actor::Property::SIZE, Vector2( windowSize.x, contentHeight ) );
206 mBottomContentArea.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::BOTTOM_CENTER );
207 mBottomContentArea.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::BOTTOM_CENTER );
208 window.Add( mBottomContentArea );
210 mSourceActor = ImageView::New(JPG_FILENAME);
211 mSourceActor.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
212 mSourceActor.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER );
213 mTopContentArea.Add( mSourceActor );
215 Animation animation = Animation::New(2.f);
216 Degree relativeRotationDegrees(90.0f);
217 Radian relativeRotationRadians(relativeRotationDegrees);
218 animation.AnimateTo( Property( mSourceActor, Actor::Property::ORIENTATION ), Quaternion( relativeRotationRadians, Vector3::ZAXIS ), AlphaFunction::LINEAR, TimePeriod(0.f, 0.5f));
219 animation.AnimateBy( Property( mSourceActor, Actor::Property::ORIENTATION ), Quaternion( relativeRotationRadians, Vector3::ZAXIS ), AlphaFunction::LINEAR, TimePeriod(0.5f, 0.5f));
220 animation.AnimateBy( Property( mSourceActor, Actor::Property::ORIENTATION ), Quaternion( relativeRotationRadians, Vector3::ZAXIS ), AlphaFunction::LINEAR, TimePeriod(1.f, 0.5f));
221 animation.AnimateBy( Property( mSourceActor, Actor::Property::ORIENTATION ), Quaternion( relativeRotationRadians, Vector3::ZAXIS ), AlphaFunction::LINEAR, TimePeriod(1.5f, 0.5f));
222 animation.SetLooping(true);
225 TextLabel textLabel1 = TextLabel::New( "Image" );
226 textLabel1.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::BOTTOM_CENTER );
227 textLabel1.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::BOTTOM_CENTER );
228 mTopContentArea.Add( textLabel1 );
230 // Wait until button press before creating mOffscreenRenderTask
232 TextLabel textLabel2 = TextLabel::New( "Native Image" );
233 textLabel2.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::BOTTOM_CENTER );
234 textLabel2.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::BOTTOM_CENTER );
235 mBottomContentArea.Add( textLabel2 );
238 void SetupNativeImage()
240 if( ! mOffscreenRenderTask )
242 Window window = mApplication.GetWindow();
243 Vector2 windowSize = window.GetSize();
245 float contentHeight( (windowSize.y - BUTTON_HEIGHT)/2.0f );
246 Vector2 imageSize( windowSize.x, contentHeight );
248 mNativeImageSourcePtr = NativeImageSource::New( imageSize.width, imageSize.height, NativeImageSource::COLOR_DEPTH_DEFAULT );
249 mNativeTexture = Texture::New( *mNativeImageSourcePtr );
251 mFrameBuffer = FrameBuffer::New( mNativeTexture.GetWidth(), mNativeTexture.GetHeight(), FrameBuffer::Attachment::NONE );
252 mFrameBuffer.AttachColorTexture( mNativeTexture );
254 mCameraActor = CameraActor::New( imageSize );
255 mCameraActor.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
256 mCameraActor.SetProperty( Actor::Property::PARENT_ORIGIN, AnchorPoint::CENTER );
257 mTopContentArea.Add( mCameraActor );
259 RenderTaskList taskList = window.GetRenderTaskList();
260 mOffscreenRenderTask = taskList.CreateTask();
261 mOffscreenRenderTask.SetSourceActor( mSourceActor );
262 mOffscreenRenderTask.SetClearColor( Color::WHITE );
263 mOffscreenRenderTask.SetClearEnabled( true );
264 mOffscreenRenderTask.SetCameraActor( mCameraActor );
265 mOffscreenRenderTask.GetCameraActor().SetInvertYAxis( true );
266 mOffscreenRenderTask.SetFrameBuffer( mFrameBuffer );
271 mOffscreenRenderTask.SetRefreshRate( RenderTask::REFRESH_ALWAYS );
275 mOffscreenRenderTask.SetRefreshRate( RenderTask::REFRESH_ONCE );
279 void SetupDisplayActor( bool show )
283 if( ! mDisplayActor )
285 // Make sure we have something to display
288 mDisplayActor = Actor::New();
289 mDisplayActor.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
290 mDisplayActor.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER );
292 Geometry geometry = DemoHelper::CreateTexturedQuad();
294 Shader shader = CreateShader( *mNativeImageSourcePtr );
296 Renderer renderer = Renderer::New( geometry, shader );
298 TextureSet textureSet = TextureSet::New();
299 textureSet.SetTexture( 0u, mNativeTexture );
300 renderer.SetTextures( textureSet );
302 mDisplayActor.AddRenderer( renderer );
303 mDisplayActor.SetProperty( Actor::Property::SIZE, Vector2( mNativeTexture.GetWidth(), mNativeTexture.GetHeight() ) );
305 mBottomContentArea.Add( mDisplayActor );
310 UnparentAndReset( mDisplayActor );
316 mRefreshAlways = false;
319 mOffscreenRenderTask.FinishedSignal().Connect( this, &NativeImageSourceController::DoCapture );
322 void DoCapture(RenderTask& task)
324 task.FinishedSignal().Disconnect( this, &NativeImageSourceController::DoCapture );
326 mNativeImageSourcePtr->EncodeToFile( CAPTURE_FILENAME );
331 SetupDisplayActor( false );
333 Window window = mApplication.GetWindow();
334 RenderTaskList taskList = window.GetRenderTaskList();
335 taskList.RemoveTask( mOffscreenRenderTask );
336 mOffscreenRenderTask.Reset();
337 mCameraActor.Reset();
339 mFrameBuffer.Reset();
340 mNativeTexture.Reset();
341 mNativeImageSourcePtr.Reset();
344 bool OnButtonSelected( Toolkit::Button button )
346 Toolkit::PushButton pushButton = Toolkit::PushButton::DownCast( button );
348 if( pushButton == mButtonShow )
350 bool isSelected = mButtonShow.GetProperty( Toolkit::Button::Property::SELECTED ).Get<bool>();
352 SetupDisplayActor( isSelected );
354 else if( pushButton == mButtonRefreshAlways )
356 bool isSelected = mButtonRefreshAlways.GetProperty( Toolkit::Button::Property::SELECTED ).Get<bool>();
358 mRefreshAlways = isSelected;
361 else if( pushButton == mButtonRefreshOnce )
363 bool isSelected = mButtonRefreshAlways.GetProperty( Toolkit::Button::Property::SELECTED ).Get<bool>();
367 mButtonRefreshAlways.SetProperty( Button::Property::SELECTED, false );
370 mRefreshAlways = false;
373 else if( pushButton == mButtonCapture )
377 else if( pushButton == mButtonReset )
385 void OnKeyEvent(const KeyEvent& event)
387 if(event.GetState() == KeyEvent::Down)
389 if( IsKey( event, Dali::DALI_KEY_ESCAPE) || IsKey( event, Dali::DALI_KEY_BACK) )
398 Application& mApplication;
401 Actor mTopContentArea;
402 Actor mBottomContentArea;
404 PushButton mButtonShow;
405 PushButton mButtonRefreshAlways;
406 PushButton mButtonRefreshOnce;
407 PushButton mButtonCapture;
408 PushButton mButtonReset;
412 NativeImageSourcePtr mNativeImageSourcePtr;
413 Texture mNativeTexture;
414 FrameBuffer mFrameBuffer;
416 RenderTask mOffscreenRenderTask;
417 CameraActor mCameraActor;
424 int DALI_EXPORT_API main( int argc, char **argv )
426 Application application = Application::New( &argc, &argv );
427 NativeImageSourceController test( application );
428 application.MainLoop();