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-toolkit/dali-toolkit.h>
20 #include <dali/dali.h>
24 #include "shared/utility.h"
27 using namespace Toolkit;
31 const float BUTTON_HEIGHT = 100.0f;
32 const float BUTTON_COUNT = 5.0f;
34 const std::string JPG_FILENAME = DEMO_IMAGE_DIR "gallery-medium-4.jpg";
35 const std::string CAPTURE_FILENAME = "/tmp/native-image-capture.png";
38 * @brief Creates a shader used to render a native image
39 * @param[in] nativeImage The native image
40 * @return A shader to render the native image
42 Shader CreateShader(NativeImageInterface& nativeImage)
44 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
104 NativeImageSourceController(Application& application)
105 : mApplication(application),
108 // Connect to the Application's Init signal
109 mApplication.InitSignal().Connect(this, &NativeImageSourceController::Create);
112 ~NativeImageSourceController()
114 // Nothing to do here;
117 // The Init signal is received once (only) during the Application lifetime
118 void Create(Application& application)
120 // Get a handle to the window
121 Window window = application.GetWindow();
122 window.SetBackgroundColor(Color::WHITE);
124 window.KeyEventSignal().Connect(this, &NativeImageSourceController::OnKeyEvent);
128 CreateContentAreas();
131 void CreateButtonArea()
133 Window window = mApplication.GetWindow();
134 Vector2 windowSize = window.GetSize();
136 mButtonArea = Layer::New();
137 mButtonArea.SetProperty(Actor::Property::SIZE, Vector2(windowSize.x, BUTTON_HEIGHT));
138 mButtonArea.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_CENTER);
139 mButtonArea.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_CENTER);
140 window.Add(mButtonArea);
142 mButtonShow = PushButton::New();
143 mButtonShow.SetProperty(Button::Property::TOGGLABLE, true);
144 mButtonShow.SetProperty(Toolkit::Button::Property::LABEL, "SHOW");
145 mButtonShow.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
146 mButtonShow.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
147 mButtonShow.SetProperty(Actor::Property::SIZE, Vector2(windowSize.x / BUTTON_COUNT, BUTTON_HEIGHT));
148 mButtonShow.ClickedSignal().Connect(this, &NativeImageSourceController::OnButtonSelected);
149 mButtonArea.Add(mButtonShow);
151 mButtonRefreshAlways = PushButton::New();
152 mButtonRefreshAlways.SetProperty(Button::Property::TOGGLABLE, true);
153 mButtonRefreshAlways.SetProperty(Toolkit::Button::Property::LABEL, "ALWAYS");
154 mButtonRefreshAlways.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
155 mButtonRefreshAlways.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
156 mButtonRefreshAlways.SetProperty(Actor::Property::SIZE, Vector2(windowSize.x / BUTTON_COUNT, BUTTON_HEIGHT));
157 mButtonRefreshAlways.SetProperty(Actor::Property::POSITION, Vector2((windowSize.x / BUTTON_COUNT) * 1.0f, 0.0f));
158 mButtonRefreshAlways.StateChangedSignal().Connect(this, &NativeImageSourceController::OnButtonSelected);
159 mButtonArea.Add(mButtonRefreshAlways);
161 mButtonRefreshOnce = PushButton::New();
162 mButtonRefreshOnce.SetProperty(Toolkit::Button::Property::LABEL, "ONCE");
163 mButtonRefreshOnce.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
164 mButtonRefreshOnce.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
165 mButtonRefreshOnce.SetProperty(Actor::Property::SIZE, Vector2(windowSize.x / BUTTON_COUNT, BUTTON_HEIGHT));
166 mButtonRefreshOnce.SetProperty(Actor::Property::POSITION, Vector2((windowSize.x / BUTTON_COUNT) * 2.0f, 0.0f));
167 mButtonRefreshOnce.ClickedSignal().Connect(this, &NativeImageSourceController::OnButtonSelected);
168 mButtonArea.Add(mButtonRefreshOnce);
170 mButtonCapture = PushButton::New();
171 mButtonCapture.SetProperty(Toolkit::Button::Property::LABEL, "CAPTURE");
172 mButtonCapture.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
173 mButtonCapture.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
174 mButtonCapture.SetProperty(Actor::Property::SIZE, Vector2(windowSize.x / BUTTON_COUNT, BUTTON_HEIGHT));
175 mButtonCapture.SetProperty(Actor::Property::POSITION, Vector2((windowSize.x / BUTTON_COUNT) * 3.0f, 0.0f));
176 mButtonCapture.ClickedSignal().Connect(this, &NativeImageSourceController::OnButtonSelected);
177 mButtonArea.Add(mButtonCapture);
179 mButtonReset = PushButton::New();
180 mButtonReset.SetProperty(Toolkit::Button::Property::LABEL, "RESET");
181 mButtonReset.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
182 mButtonReset.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
183 mButtonReset.SetProperty(Actor::Property::SIZE, Vector2(windowSize.x / BUTTON_COUNT, BUTTON_HEIGHT));
184 mButtonReset.SetProperty(Actor::Property::POSITION, Vector2((windowSize.x / BUTTON_COUNT) * 4.0f, 0.0f));
185 mButtonReset.ClickedSignal().Connect(this, &NativeImageSourceController::OnButtonSelected);
186 mButtonArea.Add(mButtonReset);
189 void CreateContentAreas()
191 Window window = mApplication.GetWindow();
192 Vector2 windowSize = window.GetSize();
194 float contentHeight((windowSize.y - BUTTON_HEIGHT) / 2.0f);
196 mTopContentArea = Actor::New();
197 mTopContentArea.SetProperty(Actor::Property::SIZE, Vector2(windowSize.x, contentHeight));
198 mTopContentArea.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_CENTER);
199 mTopContentArea.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_CENTER);
200 mTopContentArea.SetProperty(Actor::Property::POSITION_Y, BUTTON_HEIGHT);
201 window.Add(mTopContentArea);
203 mBottomContentArea = Actor::New();
204 mBottomContentArea.SetProperty(Actor::Property::SIZE, Vector2(windowSize.x, contentHeight));
205 mBottomContentArea.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::BOTTOM_CENTER);
206 mBottomContentArea.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::BOTTOM_CENTER);
207 window.Add(mBottomContentArea);
209 mSourceActor = ImageView::New(JPG_FILENAME);
210 mSourceActor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
211 mSourceActor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
212 mTopContentArea.Add(mSourceActor);
214 Animation animation = Animation::New(2.f);
215 Degree relativeRotationDegrees(90.0f);
216 Radian relativeRotationRadians(relativeRotationDegrees);
217 animation.AnimateTo(Property(mSourceActor, Actor::Property::ORIENTATION), Quaternion(relativeRotationRadians, Vector3::ZAXIS), AlphaFunction::LINEAR, TimePeriod(0.f, 0.5f));
218 animation.AnimateBy(Property(mSourceActor, Actor::Property::ORIENTATION), Quaternion(relativeRotationRadians, Vector3::ZAXIS), AlphaFunction::LINEAR, TimePeriod(0.5f, 0.5f));
219 animation.AnimateBy(Property(mSourceActor, Actor::Property::ORIENTATION), Quaternion(relativeRotationRadians, Vector3::ZAXIS), AlphaFunction::LINEAR, TimePeriod(1.f, 0.5f));
220 animation.AnimateBy(Property(mSourceActor, Actor::Property::ORIENTATION), Quaternion(relativeRotationRadians, Vector3::ZAXIS), AlphaFunction::LINEAR, TimePeriod(1.5f, 0.5f));
221 animation.SetLooping(true);
224 TextLabel textLabel1 = TextLabel::New("Image");
225 textLabel1.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::BOTTOM_CENTER);
226 textLabel1.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::BOTTOM_CENTER);
227 mTopContentArea.Add(textLabel1);
229 // Wait until button press before creating mOffscreenRenderTask
231 TextLabel textLabel2 = TextLabel::New("Native Image");
232 textLabel2.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::BOTTOM_CENTER);
233 textLabel2.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::BOTTOM_CENTER);
234 mBottomContentArea.Add(textLabel2);
237 void SetupNativeImage()
239 if(!mOffscreenRenderTask)
241 Window window = mApplication.GetWindow();
242 Vector2 windowSize = window.GetSize();
244 float contentHeight((windowSize.y - BUTTON_HEIGHT) / 2.0f);
245 Vector2 imageSize(windowSize.x, contentHeight);
247 mNativeImageSourcePtr = NativeImageSource::New(imageSize.width, imageSize.height, NativeImageSource::COLOR_DEPTH_DEFAULT);
248 mNativeTexture = Texture::New(*mNativeImageSourcePtr);
250 mFrameBuffer = FrameBuffer::New(mNativeTexture.GetWidth(), mNativeTexture.GetHeight(), FrameBuffer::Attachment::NONE);
251 mFrameBuffer.AttachColorTexture(mNativeTexture);
253 mCameraActor = CameraActor::New(imageSize);
254 mCameraActor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
255 mCameraActor.SetProperty(Actor::Property::PARENT_ORIGIN, AnchorPoint::CENTER);
256 mTopContentArea.Add(mCameraActor);
258 RenderTaskList taskList = window.GetRenderTaskList();
259 mOffscreenRenderTask = taskList.CreateTask();
260 mOffscreenRenderTask.SetSourceActor(mSourceActor);
261 mOffscreenRenderTask.SetClearColor(Color::WHITE);
262 mOffscreenRenderTask.SetClearEnabled(true);
263 mOffscreenRenderTask.SetCameraActor(mCameraActor);
264 mOffscreenRenderTask.GetCameraActor().SetInvertYAxis(true);
265 mOffscreenRenderTask.SetFrameBuffer(mFrameBuffer);
270 mOffscreenRenderTask.SetRefreshRate(RenderTask::REFRESH_ALWAYS);
274 mOffscreenRenderTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
278 void SetupDisplayActor(bool show)
284 // Make sure we have something to display
287 mDisplayActor = Actor::New();
288 mDisplayActor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
289 mDisplayActor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
291 Geometry geometry = DemoHelper::CreateTexturedQuad();
293 Shader shader = CreateShader(*mNativeImageSourcePtr);
295 Renderer renderer = Renderer::New(geometry, shader);
297 TextureSet textureSet = TextureSet::New();
298 textureSet.SetTexture(0u, mNativeTexture);
299 renderer.SetTextures(textureSet);
301 mDisplayActor.AddRenderer(renderer);
302 mDisplayActor.SetProperty(Actor::Property::SIZE, Vector2(mNativeTexture.GetWidth(), mNativeTexture.GetHeight()));
304 mBottomContentArea.Add(mDisplayActor);
309 UnparentAndReset(mDisplayActor);
315 mRefreshAlways = false;
318 mOffscreenRenderTask.FinishedSignal().Connect(this, &NativeImageSourceController::DoCapture);
321 void DoCapture(RenderTask& task)
323 task.FinishedSignal().Disconnect(this, &NativeImageSourceController::DoCapture);
325 mNativeImageSourcePtr->EncodeToFile(CAPTURE_FILENAME);
330 SetupDisplayActor(false);
332 Window window = mApplication.GetWindow();
333 RenderTaskList taskList = window.GetRenderTaskList();
334 taskList.RemoveTask(mOffscreenRenderTask);
335 mOffscreenRenderTask.Reset();
336 mCameraActor.Reset();
338 mFrameBuffer.Reset();
339 mNativeTexture.Reset();
340 mNativeImageSourcePtr.Reset();
343 bool OnButtonSelected(Toolkit::Button button)
345 Toolkit::PushButton pushButton = Toolkit::PushButton::DownCast(button);
347 if(pushButton == mButtonShow)
349 bool isSelected = mButtonShow.GetProperty(Toolkit::Button::Property::SELECTED).Get<bool>();
351 SetupDisplayActor(isSelected);
353 else if(pushButton == mButtonRefreshAlways)
355 bool isSelected = mButtonRefreshAlways.GetProperty(Toolkit::Button::Property::SELECTED).Get<bool>();
357 mRefreshAlways = isSelected;
360 else if(pushButton == mButtonRefreshOnce)
362 bool isSelected = mButtonRefreshAlways.GetProperty(Toolkit::Button::Property::SELECTED).Get<bool>();
366 mButtonRefreshAlways.SetProperty(Button::Property::SELECTED, false);
369 mRefreshAlways = false;
372 else if(pushButton == mButtonCapture)
376 else if(pushButton == mButtonReset)
384 void OnKeyEvent(const KeyEvent& event)
386 if(event.GetState() == KeyEvent::DOWN)
388 if(IsKey(event, Dali::DALI_KEY_ESCAPE) || IsKey(event, Dali::DALI_KEY_BACK))
396 Application& mApplication;
399 Actor mTopContentArea;
400 Actor mBottomContentArea;
402 PushButton mButtonShow;
403 PushButton mButtonRefreshAlways;
404 PushButton mButtonRefreshOnce;
405 PushButton mButtonCapture;
406 PushButton mButtonReset;
410 NativeImageSourcePtr mNativeImageSourcePtr;
411 Texture mNativeTexture;
412 FrameBuffer mFrameBuffer;
414 RenderTask mOffscreenRenderTask;
415 CameraActor mCameraActor;
422 int DALI_EXPORT_API main(int argc, char** argv)
424 Application application = Application::New(&argc, &argv);
425 NativeImageSourceController test(application);
426 application.MainLoop();