2 * Copyright (c) 2016 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 );
149 stage.KeyEventSignal().Connect(this, &NativeImageSourceController::OnKeyEvent);
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 );
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);
172 Stage stage = Stage::GetCurrent();
173 Vector2 stageSize = stage.GetSize();
175 float buttonHeight = 100.f;
176 mButtonRefreshAlways.SetSize( stageSize.x / 2.f, buttonHeight );
177 mButtonRefreshOnce.SetSize( stageSize.x / 2.f, buttonHeight );
179 Vector2 imageSize( stageSize.x, (stageSize.y-buttonHeight)/2.f );
181 // Create the native image source
182 NativeImageSourcePtr nativeImageSourcePtr = NativeImageSource::New( imageSize.width, imageSize.height, NativeImageSource::COLOR_DEPTH_DEFAULT );
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 );
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);
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 );
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);
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 );
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 );
230 TextLabel textLabel1 = TextLabel::New( "Resource Image" );
231 textLabel1.SetParentOrigin( ParentOrigin::TOP_CENTER );
232 textLabel1.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
233 nativeImageActor.Add( textLabel1 );
235 TextLabel textLabel2 = TextLabel::New( "Native Image" );
236 textLabel2.SetParentOrigin( ParentOrigin::BOTTOM_CENTER );
237 textLabel2.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
238 nativeImageActor.Add( textLabel2 );
243 bool OnButtonSelected( Toolkit::Button button )
245 Toolkit::PushButton pushButton = Toolkit::PushButton::DownCast( button );
246 if( pushButton == mButtonRefreshAlways )
248 if( mButtonRefreshAlways.IsSelected() )
250 mOffscreenRenderTask.SetRefreshRate( RenderTask::REFRESH_ALWAYS );
254 mOffscreenRenderTask.SetRefreshRate( RenderTask::REFRESH_ONCE );
257 else if( pushButton == mButtonRefreshOnce )
259 if( mButtonRefreshAlways.IsSelected() )
261 mButtonRefreshAlways.SetSelected( false );
263 mOffscreenRenderTask.SetRefreshRate( RenderTask::REFRESH_ONCE );
269 void OnKeyEvent(const KeyEvent& event)
271 if(event.state == KeyEvent::Down)
273 if( IsKey( event, Dali::DALI_KEY_ESCAPE) || IsKey( event, Dali::DALI_KEY_BACK) )
281 Application& mApplication;
282 RenderTask mOffscreenRenderTask;
283 PushButton mButtonRefreshAlways;
284 PushButton mButtonRefreshOnce;
288 void RunTest( Application& application )
290 NativeImageSourceController test( application );
292 application.MainLoop();
295 // Entry point for Linux & Tizen applications
297 int DALI_EXPORT_API main( int argc, char **argv )
299 Application application = Application::New( &argc, &argv );
301 RunTest( application );