[dali_1.1.43] Merge branch 'devel/master'
[platform/core/uifw/dali-demo.git] / examples / native-image-source / native-image-source-example.cpp
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
18 // EXTERNAL INCLUDES
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>
24 #include <cstring>
25
26 // INTERNAL INCLUDES
27 #include "shared/utility.h"
28
29 using namespace Dali;
30 using namespace Toolkit;
31
32 namespace
33 {
34
35 /**
36  * @brief Creates a shader used to render a native image
37  * @param[in] nativeImageInterface The native image interface
38  * @return A shader to render the native image
39  */
40 Shader CreateShader( NativeImageInterface& nativeImageInterface )
41 {
42   static const char* DEFAULT_SAMPLER_TYPENAME = "sampler2D";
43
44   static const char* VERTEX_SHADER_TEXTURE = DALI_COMPOSE_SHADER(
45       attribute mediump vec2 aPosition;\n
46       attribute mediump vec2 aTexCoord;\n
47       uniform mediump mat4 uMvpMatrix;\n
48       uniform mediump vec3 uSize;\n
49       varying mediump vec2 vTexCoord;\n
50       void main()\n
51       {\n
52         vec4 position = vec4(aPosition,0.0,1.0)*vec4(uSize,1.0);\n
53         gl_Position = uMvpMatrix * position;\n
54         vTexCoord = aTexCoord;\n
55       }\n
56   );
57
58   static const char* FRAGMENT_SHADER_TEXTURE = DALI_COMPOSE_SHADER(
59       uniform lowp vec4 uColor;\n
60       uniform sampler2D sTexture;\n
61       varying mediump vec2 vTexCoord;\n
62
63       void main()\n
64       {\n
65         gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor;\n
66       }\n
67   );
68
69   NativeImageInterface::Extension* extension( nativeImageInterface.GetExtension() );
70   if( extension )
71   {
72     std::string fragmentShader;
73
74     //Get custom fragment shader prefix
75     const char* fragmentPreFix = extension->GetCustomFragmentPreFix();
76     if( fragmentPreFix )
77     {
78       fragmentShader = fragmentPreFix;
79       fragmentShader += FRAGMENT_SHADER_TEXTURE;
80     }
81     else
82     {
83       fragmentShader = FRAGMENT_SHADER_TEXTURE;
84     }
85
86     //Get custom sampler type name
87     const char* customSamplerTypename = extension->GetCustomSamplerTypename();
88     if( customSamplerTypename )
89     {
90       fragmentShader.replace( fragmentShader.find( DEFAULT_SAMPLER_TYPENAME ), strlen(DEFAULT_SAMPLER_TYPENAME), customSamplerTypename );
91     }
92
93     return Shader::New( VERTEX_SHADER_TEXTURE, fragmentShader );
94   }
95   else
96   {
97     return Shader::New( VERTEX_SHADER_TEXTURE, FRAGMENT_SHADER_TEXTURE );
98   }
99 }
100
101 /**
102  * @brief Creates an actor to render a native image
103  * @param[in] texture The texture creates from a native image
104  * @param[in] nativeImageInterface The native image interface used to create the texture
105  * @return An actor that renders the texture
106  */
107 Actor CreateNativeActor( Texture texture, NativeImageInterface& nativeImageInterface )
108 {
109   Actor actor = Actor::New();
110   Geometry geometry = DemoHelper::CreateTexturedQuad();
111   Shader shader = CreateShader(nativeImageInterface);
112   Renderer renderer = Renderer::New( geometry, shader );
113   TextureSet textureSet = TextureSet::New();
114   textureSet.SetTexture( 0u, texture );
115   renderer.SetTextures( textureSet );
116
117   actor.AddRenderer( renderer );
118   actor.SetSize( texture.GetWidth(), texture.GetHeight() );
119   return actor;
120 }
121
122 const std::string JPG_FILENAME = DEMO_IMAGE_DIR "gallery-medium-4.jpg";
123 }
124
125 // This example shows how to create and use a NativeImageSource as the target of the render task.
126 //
127 class NativeImageSourceController : public ConnectionTracker
128 {
129 public:
130
131   NativeImageSourceController( Application& application )
132   : mApplication( application )
133   {
134     // Connect to the Application's Init signal
135     mApplication.InitSignal().Connect( this, &NativeImageSourceController::Create );
136   }
137
138   ~NativeImageSourceController()
139   {
140     // Nothing to do here;
141   }
142
143   // The Init signal is received once (only) during the Application lifetime
144   void Create( Application& application )
145   {
146     // Get a handle to the stage
147     Stage stage = Stage::GetCurrent();
148     stage.SetBackgroundColor( Color::WHITE );
149     stage.KeyEventSignal().Connect(this, &NativeImageSourceController::OnKeyEvent);
150
151     mButtonRefreshAlways = PushButton::New();
152     mButtonRefreshAlways.SetTogglableButton( true );
153     mButtonRefreshAlways.SetSelected( true );
154     mButtonRefreshAlways.SetLabelText( "Refresh ALWAYS" );
155     mButtonRefreshAlways.SetParentOrigin( ParentOrigin::TOP_LEFT );
156     mButtonRefreshAlways.SetAnchorPoint( AnchorPoint::TOP_LEFT );
157     mButtonRefreshAlways.StateChangedSignal().Connect( this, &NativeImageSourceController::OnButtonSelected );
158     stage.Add( mButtonRefreshAlways );
159
160     mButtonRefreshOnce = PushButton::New();
161     mButtonRefreshOnce.SetLabelText( "Refresh ONCE" );
162     mButtonRefreshOnce.SetParentOrigin( ParentOrigin::TOP_RIGHT );
163     mButtonRefreshOnce.SetAnchorPoint( AnchorPoint::TOP_RIGHT );
164     mButtonRefreshOnce.ClickedSignal().Connect( this, &NativeImageSourceController::OnButtonSelected );
165     stage.Add( mButtonRefreshOnce);
166
167     CreateScene();
168   }
169
170   bool CreateScene()
171   {
172     Stage stage = Stage::GetCurrent();
173     Vector2 stageSize = stage.GetSize();
174
175     float buttonHeight = 100.f;
176     mButtonRefreshAlways.SetSize( stageSize.x / 2.f, buttonHeight );
177     mButtonRefreshOnce.SetSize( stageSize.x / 2.f, buttonHeight );
178
179     Vector2 imageSize( stageSize.x, (stageSize.y-buttonHeight)/2.f );
180
181     // Create the native image source
182     NativeImageSourcePtr nativeImageSourcePtr = NativeImageSource::New( imageSize.width, imageSize.height, NativeImageSource::COLOR_DEPTH_DEFAULT );
183
184     // Create a image view as source actor to be renderer to the native image source
185     Actor sourceActor = ImageView::New(JPG_FILENAME);
186     sourceActor.SetParentOrigin( ParentOrigin::CENTER);
187     sourceActor.SetAnchorPoint( AnchorPoint::CENTER );
188     sourceActor.SetY( - (imageSize.height-buttonHeight)/2.f );
189     stage.Add( sourceActor );
190
191     Animation animation = Animation::New(2.f);
192     Degree relativeRotationDegrees(90.0f);
193     Radian relativeRotationRadians(relativeRotationDegrees);
194     animation.AnimateTo( Property( sourceActor, Actor::Property::ORIENTATION ), Quaternion( relativeRotationRadians, Vector3::ZAXIS ), AlphaFunction::LINEAR, TimePeriod(0.f, 0.5f));
195     animation.AnimateBy( Property( sourceActor, Actor::Property::ORIENTATION ), Quaternion( relativeRotationRadians, Vector3::ZAXIS ), AlphaFunction::LINEAR, TimePeriod(0.5f, 0.5f));
196     animation.AnimateBy( Property( sourceActor, Actor::Property::ORIENTATION ), Quaternion( relativeRotationRadians, Vector3::ZAXIS ), AlphaFunction::LINEAR, TimePeriod(1.f, 0.5f));
197     animation.AnimateBy( Property( sourceActor, Actor::Property::ORIENTATION ), Quaternion( relativeRotationRadians, Vector3::ZAXIS ), AlphaFunction::LINEAR, TimePeriod(1.5f, 0.5f));
198     animation.SetLooping(true);
199     animation.Play();
200
201     // create a offscreen renderer task to render content into the native image source
202     Texture nativeTexture = Texture::New( *nativeImageSourcePtr );
203     FrameBuffer targetBuffer = FrameBuffer::New( nativeTexture.GetWidth(), nativeTexture.GetHeight(), FrameBuffer::COLOR );
204     targetBuffer.AttachColorTexture( nativeTexture );
205
206     CameraActor cameraActor = CameraActor::New(imageSize);
207     cameraActor.SetParentOrigin(ParentOrigin::TOP_CENTER);
208     cameraActor.SetParentOrigin( AnchorPoint::TOP_CENTER );
209     cameraActor.SetY( buttonHeight + imageSize.height/2.f );
210     stage.Add(cameraActor);
211
212     RenderTaskList taskList = stage.GetRenderTaskList();
213     mOffscreenRenderTask = taskList.CreateTask();
214     mOffscreenRenderTask.SetSourceActor( sourceActor );
215     mOffscreenRenderTask.SetClearColor( Color::WHITE );
216     mOffscreenRenderTask.SetClearEnabled(true);
217     mOffscreenRenderTask.SetCameraActor(cameraActor);
218     mOffscreenRenderTask.GetCameraActor().SetInvertYAxis(true);
219     mOffscreenRenderTask.SetFrameBuffer( targetBuffer );
220     mOffscreenRenderTask.SetRefreshRate( RenderTask::REFRESH_ALWAYS );
221
222     // Display the native image on the screen
223     Actor nativeImageActor = CreateNativeActor( nativeTexture, *nativeImageSourcePtr );
224     nativeImageActor.SetParentOrigin( ParentOrigin::BOTTOM_CENTER );
225     nativeImageActor.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
226     stage.Add( nativeImageActor );
227
228     TextLabel textLabel1 = TextLabel::New( "Resource Image" );
229     textLabel1.SetParentOrigin( ParentOrigin::TOP_CENTER );
230     textLabel1.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
231     nativeImageActor.Add( textLabel1 );
232
233     TextLabel textLabel2 = TextLabel::New( "Native Image" );
234     textLabel2.SetParentOrigin( ParentOrigin::BOTTOM_CENTER );
235     textLabel2.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
236     nativeImageActor.Add( textLabel2 );
237
238     return false;
239   }
240
241   bool OnButtonSelected( Toolkit::Button button )
242   {
243     Toolkit::PushButton pushButton = Toolkit::PushButton::DownCast( button );
244     if( pushButton == mButtonRefreshAlways )
245     {
246       if( mButtonRefreshAlways.IsSelected() )
247       {
248         mOffscreenRenderTask.SetRefreshRate( RenderTask::REFRESH_ALWAYS );
249       }
250       else
251       {
252         mOffscreenRenderTask.SetRefreshRate( RenderTask::REFRESH_ONCE );
253       }
254     }
255     else if( pushButton == mButtonRefreshOnce )
256     {
257       if( mButtonRefreshAlways.IsSelected() )
258       {
259         mButtonRefreshAlways.SetSelected( false );
260       }
261       mOffscreenRenderTask.SetRefreshRate( RenderTask::REFRESH_ONCE );
262     }
263
264     return true;
265   }
266
267   void OnKeyEvent(const KeyEvent& event)
268   {
269     if(event.state == KeyEvent::Down)
270     {
271       if( IsKey( event, Dali::DALI_KEY_ESCAPE) || IsKey( event, Dali::DALI_KEY_BACK) )
272       {
273         mApplication.Quit();
274       }
275     }
276   }
277
278 private:
279   Application&  mApplication;
280   RenderTask mOffscreenRenderTask;
281   PushButton mButtonRefreshAlways;
282   PushButton mButtonRefreshOnce;
283
284 };
285
286 void RunTest( Application& application )
287 {
288   NativeImageSourceController test( application );
289
290   application.MainLoop();
291 }
292
293 // Entry point for Linux & Tizen applications
294 //
295 int DALI_EXPORT_API main( int argc, char **argv )
296 {
297   Application application = Application::New( &argc, &argv );
298
299   RunTest( application );
300
301   return 0;
302 }