fe676dcabec86e89b91c61c41a6333ccec5c5966
[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     // Create a FrameBuffer object with no default attachments.
204     FrameBuffer targetBuffer = FrameBuffer::New( nativeTexture.GetWidth(), nativeTexture.GetHeight(), FrameBuffer::Attachment::NONE );
205     // Add a color attachment to the FrameBuffer object.
206     targetBuffer.AttachColorTexture( nativeTexture );
207
208     CameraActor cameraActor = CameraActor::New(imageSize);
209     cameraActor.SetParentOrigin(ParentOrigin::TOP_CENTER);
210     cameraActor.SetParentOrigin( AnchorPoint::TOP_CENTER );
211     cameraActor.SetY( buttonHeight + imageSize.height/2.f );
212     stage.Add(cameraActor);
213
214     RenderTaskList taskList = stage.GetRenderTaskList();
215     mOffscreenRenderTask = taskList.CreateTask();
216     mOffscreenRenderTask.SetSourceActor( sourceActor );
217     mOffscreenRenderTask.SetClearColor( Color::WHITE );
218     mOffscreenRenderTask.SetClearEnabled(true);
219     mOffscreenRenderTask.SetCameraActor(cameraActor);
220     mOffscreenRenderTask.GetCameraActor().SetInvertYAxis(true);
221     mOffscreenRenderTask.SetFrameBuffer( targetBuffer );
222     mOffscreenRenderTask.SetRefreshRate( RenderTask::REFRESH_ALWAYS );
223
224     // Display the native image on the screen
225     Actor nativeImageActor = CreateNativeActor( nativeTexture, *nativeImageSourcePtr );
226     nativeImageActor.SetParentOrigin( ParentOrigin::BOTTOM_CENTER );
227     nativeImageActor.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
228     stage.Add( nativeImageActor );
229
230     TextLabel textLabel1 = TextLabel::New( "Resource Image" );
231     textLabel1.SetParentOrigin( ParentOrigin::TOP_CENTER );
232     textLabel1.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
233     nativeImageActor.Add( textLabel1 );
234
235     TextLabel textLabel2 = TextLabel::New( "Native Image" );
236     textLabel2.SetParentOrigin( ParentOrigin::BOTTOM_CENTER );
237     textLabel2.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
238     nativeImageActor.Add( textLabel2 );
239
240     return false;
241   }
242
243   bool OnButtonSelected( Toolkit::Button button )
244   {
245     Toolkit::PushButton pushButton = Toolkit::PushButton::DownCast( button );
246     if( pushButton == mButtonRefreshAlways )
247     {
248       if( mButtonRefreshAlways.IsSelected() )
249       {
250         mOffscreenRenderTask.SetRefreshRate( RenderTask::REFRESH_ALWAYS );
251       }
252       else
253       {
254         mOffscreenRenderTask.SetRefreshRate( RenderTask::REFRESH_ONCE );
255       }
256     }
257     else if( pushButton == mButtonRefreshOnce )
258     {
259       if( mButtonRefreshAlways.IsSelected() )
260       {
261         mButtonRefreshAlways.SetSelected( false );
262       }
263       mOffscreenRenderTask.SetRefreshRate( RenderTask::REFRESH_ONCE );
264     }
265
266     return true;
267   }
268
269   void OnKeyEvent(const KeyEvent& event)
270   {
271     if(event.state == KeyEvent::Down)
272     {
273       if( IsKey( event, Dali::DALI_KEY_ESCAPE) || IsKey( event, Dali::DALI_KEY_BACK) )
274       {
275         mApplication.Quit();
276       }
277     }
278   }
279
280 private:
281   Application&  mApplication;
282   RenderTask mOffscreenRenderTask;
283   PushButton mButtonRefreshAlways;
284   PushButton mButtonRefreshOnce;
285
286 };
287
288 void RunTest( Application& application )
289 {
290   NativeImageSourceController test( application );
291
292   application.MainLoop();
293 }
294
295 // Entry point for Linux & Tizen applications
296 //
297 int DALI_EXPORT_API main( int argc, char **argv )
298 {
299   Application application = Application::New( &argc, &argv );
300
301   RunTest( application );
302
303   return 0;
304 }