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;
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
40 Shader CreateShader( NativeImageInterface& nativeImageInterface )
42 static const char* DEFAULT_SAMPLER_TYPENAME = "sampler2D";
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
52 vec4 position = vec4(aPosition,0.0,1.0)*vec4(uSize,1.0);\n
53 gl_Position = uMvpMatrix * position;\n
54 vTexCoord = aTexCoord;\n
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
65 gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor;\n
69 NativeImageInterface::Extension* extension( nativeImageInterface.GetExtension() );
72 std::string fragmentShader;
74 //Get custom fragment shader prefix
75 const char* fragmentPreFix = extension->GetCustomFragmentPreFix();
78 fragmentShader = fragmentPreFix;
79 fragmentShader += FRAGMENT_SHADER_TEXTURE;
83 fragmentShader = FRAGMENT_SHADER_TEXTURE;
86 //Get custom sampler type name
87 const char* customSamplerTypename = extension->GetCustomSamplerTypename();
88 if( customSamplerTypename )
90 fragmentShader.replace( fragmentShader.find( DEFAULT_SAMPLER_TYPENAME ), strlen(DEFAULT_SAMPLER_TYPENAME), customSamplerTypename );
93 return Shader::New( VERTEX_SHADER_TEXTURE, fragmentShader );
97 return Shader::New( VERTEX_SHADER_TEXTURE, FRAGMENT_SHADER_TEXTURE );
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
107 Actor CreateNativeActor( Texture texture, NativeImageInterface& nativeImageInterface )
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 );
117 actor.AddRenderer( renderer );
118 actor.SetSize( texture.GetWidth(), texture.GetHeight() );
122 const std::string JPG_FILENAME = DEMO_IMAGE_DIR "gallery-medium-4.jpg";
125 // This example shows how to create and use a NativeImageSource as the target of the render task.
127 class NativeImageSourceController : public ConnectionTracker
131 NativeImageSourceController( Application& application )
132 : mApplication( application )
134 // Connect to the Application's Init signal
135 mApplication.InitSignal().Connect( this, &NativeImageSourceController::Create );
138 ~NativeImageSourceController()
140 // Nothing to do here;
143 // The Init signal is received once (only) during the Application lifetime
144 void Create( Application& application )
146 // Get a handle to the stage
147 Stage stage = Stage::GetCurrent();
148 stage.SetBackgroundColor( Color::WHITE );
150 // Hide the indicator bar
151 application.GetWindow().ShowIndicator( Dali::Window::INVISIBLE );
153 stage.KeyEventSignal().Connect(this, &NativeImageSourceController::OnKeyEvent);
155 mButtonRefreshAlways = PushButton::New();
156 mButtonRefreshAlways.SetProperty( Button::Property::TOGGLABLE, true );
157 mButtonRefreshAlways.SetProperty( Button::Property::SELECTED, true );
158 mButtonRefreshAlways.SetProperty( Toolkit::Button::Property::LABEL, "Refresh ALWAYS" );
159 mButtonRefreshAlways.SetParentOrigin( ParentOrigin::TOP_LEFT );
160 mButtonRefreshAlways.SetAnchorPoint( AnchorPoint::TOP_LEFT );
161 mButtonRefreshAlways.StateChangedSignal().Connect( this, &NativeImageSourceController::OnButtonSelected );
162 stage.Add( mButtonRefreshAlways );
164 mButtonRefreshOnce = PushButton::New();
165 mButtonRefreshOnce.SetProperty( Toolkit::Button::Property::LABEL, "Refresh ONCE" );
166 mButtonRefreshOnce.SetParentOrigin( ParentOrigin::TOP_RIGHT );
167 mButtonRefreshOnce.SetAnchorPoint( AnchorPoint::TOP_RIGHT );
168 mButtonRefreshOnce.ClickedSignal().Connect( this, &NativeImageSourceController::OnButtonSelected );
169 stage.Add( mButtonRefreshOnce);
176 Stage stage = Stage::GetCurrent();
177 Vector2 stageSize = stage.GetSize();
179 float buttonHeight = 100.f;
180 mButtonRefreshAlways.SetSize( stageSize.x / 2.f, buttonHeight );
181 mButtonRefreshOnce.SetSize( stageSize.x / 2.f, buttonHeight );
183 Vector2 imageSize( stageSize.x, (stageSize.y-buttonHeight)/2.f );
185 // Create the native image source
186 NativeImageSourcePtr nativeImageSourcePtr = NativeImageSource::New( imageSize.width, imageSize.height, NativeImageSource::COLOR_DEPTH_DEFAULT );
188 // Create a image view as source actor to be renderer to the native image source
189 Actor sourceActor = ImageView::New(JPG_FILENAME);
190 sourceActor.SetParentOrigin( ParentOrigin::CENTER);
191 sourceActor.SetAnchorPoint( AnchorPoint::CENTER );
192 sourceActor.SetY( - (imageSize.height-buttonHeight)/2.f );
193 stage.Add( sourceActor );
195 Animation animation = Animation::New(2.f);
196 Degree relativeRotationDegrees(90.0f);
197 Radian relativeRotationRadians(relativeRotationDegrees);
198 animation.AnimateTo( Property( sourceActor, Actor::Property::ORIENTATION ), Quaternion( relativeRotationRadians, Vector3::ZAXIS ), AlphaFunction::LINEAR, TimePeriod(0.f, 0.5f));
199 animation.AnimateBy( Property( sourceActor, Actor::Property::ORIENTATION ), Quaternion( relativeRotationRadians, Vector3::ZAXIS ), AlphaFunction::LINEAR, TimePeriod(0.5f, 0.5f));
200 animation.AnimateBy( Property( sourceActor, Actor::Property::ORIENTATION ), Quaternion( relativeRotationRadians, Vector3::ZAXIS ), AlphaFunction::LINEAR, TimePeriod(1.f, 0.5f));
201 animation.AnimateBy( Property( sourceActor, Actor::Property::ORIENTATION ), Quaternion( relativeRotationRadians, Vector3::ZAXIS ), AlphaFunction::LINEAR, TimePeriod(1.5f, 0.5f));
202 animation.SetLooping(true);
205 // create a offscreen renderer task to render content into the native image source
206 Texture nativeTexture = Texture::New( *nativeImageSourcePtr );
207 // Create a FrameBuffer object with no default attachments.
208 FrameBuffer targetBuffer = FrameBuffer::New( nativeTexture.GetWidth(), nativeTexture.GetHeight(), FrameBuffer::Attachment::NONE );
209 // Add a color attachment to the FrameBuffer object.
210 targetBuffer.AttachColorTexture( nativeTexture );
212 CameraActor cameraActor = CameraActor::New(imageSize);
213 cameraActor.SetParentOrigin(ParentOrigin::TOP_CENTER);
214 cameraActor.SetParentOrigin( AnchorPoint::TOP_CENTER );
215 cameraActor.SetY( buttonHeight + imageSize.height/2.f );
216 stage.Add(cameraActor);
218 RenderTaskList taskList = stage.GetRenderTaskList();
219 mOffscreenRenderTask = taskList.CreateTask();
220 mOffscreenRenderTask.SetSourceActor( sourceActor );
221 mOffscreenRenderTask.SetClearColor( Color::WHITE );
222 mOffscreenRenderTask.SetClearEnabled(true);
223 mOffscreenRenderTask.SetCameraActor(cameraActor);
224 mOffscreenRenderTask.GetCameraActor().SetInvertYAxis(true);
225 mOffscreenRenderTask.SetFrameBuffer( targetBuffer );
226 mOffscreenRenderTask.SetRefreshRate( RenderTask::REFRESH_ALWAYS );
228 // Display the native image on the screen
229 Actor nativeImageActor = CreateNativeActor( nativeTexture, *nativeImageSourcePtr );
230 nativeImageActor.SetParentOrigin( ParentOrigin::BOTTOM_CENTER );
231 nativeImageActor.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
232 stage.Add( nativeImageActor );
234 TextLabel textLabel1 = TextLabel::New( "Resource Image" );
235 textLabel1.SetParentOrigin( ParentOrigin::TOP_CENTER );
236 textLabel1.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
237 nativeImageActor.Add( textLabel1 );
239 TextLabel textLabel2 = TextLabel::New( "Native Image" );
240 textLabel2.SetParentOrigin( ParentOrigin::BOTTOM_CENTER );
241 textLabel2.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
242 nativeImageActor.Add( textLabel2 );
247 bool OnButtonSelected( Toolkit::Button button )
249 bool isSelected = mButtonRefreshAlways.GetProperty( Toolkit::Button::Property::SELECTED ).Get<bool>();
251 Toolkit::PushButton pushButton = Toolkit::PushButton::DownCast( button );
252 if( pushButton == mButtonRefreshAlways )
256 mOffscreenRenderTask.SetRefreshRate( RenderTask::REFRESH_ALWAYS );
260 mOffscreenRenderTask.SetRefreshRate( RenderTask::REFRESH_ONCE );
263 else if( pushButton == mButtonRefreshOnce )
267 mButtonRefreshAlways.SetProperty( Button::Property::SELECTED, false );
269 mOffscreenRenderTask.SetRefreshRate( RenderTask::REFRESH_ONCE );
275 void OnKeyEvent(const KeyEvent& event)
277 if(event.state == KeyEvent::Down)
279 if( IsKey( event, Dali::DALI_KEY_ESCAPE) || IsKey( event, Dali::DALI_KEY_BACK) )
287 Application& mApplication;
288 RenderTask mOffscreenRenderTask;
289 PushButton mButtonRefreshAlways;
290 PushButton mButtonRefreshOnce;
294 void RunTest( Application& application )
296 NativeImageSourceController test( application );
298 application.MainLoop();
301 // Entry point for Linux & Tizen applications
303 int DALI_EXPORT_API main( int argc, char **argv )
305 Application application = Application::New( &argc, &argv );
307 RunTest( application );