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"
25 #include "generated/native-image-source-texture-vert.h"
26 #include "generated/native-image-source-texture-frag.h"
29 using namespace Toolkit;
33 const float BUTTON_HEIGHT = 100.0f;
34 const float BUTTON_COUNT = 5.0f;
36 const std::string JPG_FILENAME = DEMO_IMAGE_DIR "gallery-medium-4.jpg";
37 const std::string CAPTURE_FILENAME = DEMO_DATA_PUBLIC_RW_DIR "native-image-capture.png";
40 * @brief Creates a shader used to render a native image
41 * @param[in] nativeImage The native image
42 * @return A shader to render the native image
44 Shader CreateShader(NativeImageInterface& nativeImage)
46 static const char* DEFAULT_SAMPLER_TYPENAME = "sampler2D";
48 std::string fragmentShader;
50 //Get custom fragment shader prefix
51 const char* fragmentPrefix = nativeImage.GetCustomFragmentPrefix();
54 fragmentShader = fragmentPrefix;
55 fragmentShader += SHADER_NATIVE_IMAGE_SOURCE_TEXTURE_FRAG.data();
59 fragmentShader = SHADER_NATIVE_IMAGE_SOURCE_TEXTURE_FRAG.data();
62 //Get custom sampler type name
63 const char* customSamplerTypename = nativeImage.GetCustomSamplerTypename();
64 if(customSamplerTypename)
66 fragmentShader.replace(fragmentShader.find(DEFAULT_SAMPLER_TYPENAME), strlen(DEFAULT_SAMPLER_TYPENAME), customSamplerTypename);
69 return Shader::New(SHADER_NATIVE_IMAGE_SOURCE_TEXTURE_VERT, fragmentShader);
74 // This example shows how to create and use a NativeImageSource as the target of the render task.
76 class NativeImageSourceController : public ConnectionTracker
79 NativeImageSourceController(Application& application)
80 : mApplication(application),
83 // Connect to the Application's Init signal
84 mApplication.InitSignal().Connect(this, &NativeImageSourceController::Create);
87 ~NativeImageSourceController()
89 // Nothing to do here;
92 // The Init signal is received once (only) during the Application lifetime
93 void Create(Application& application)
95 // Get a handle to the window
96 Window window = application.GetWindow();
97 window.SetBackgroundColor(Color::WHITE);
99 window.KeyEventSignal().Connect(this, &NativeImageSourceController::OnKeyEvent);
103 CreateContentAreas();
106 void CreateButtonArea()
108 Window window = mApplication.GetWindow();
109 Vector2 windowSize = window.GetSize();
111 mButtonArea = Layer::New();
112 mButtonArea.SetProperty(Actor::Property::SIZE, Vector2(windowSize.x, BUTTON_HEIGHT));
113 mButtonArea.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_CENTER);
114 mButtonArea.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_CENTER);
115 window.Add(mButtonArea);
117 mButtonShow = PushButton::New();
118 mButtonShow.SetProperty(Button::Property::TOGGLABLE, true);
119 mButtonShow.SetProperty(Toolkit::Button::Property::LABEL, "SHOW");
120 mButtonShow.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
121 mButtonShow.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
122 mButtonShow.SetProperty(Actor::Property::SIZE, Vector2(windowSize.x / BUTTON_COUNT, BUTTON_HEIGHT));
123 mButtonShow.ClickedSignal().Connect(this, &NativeImageSourceController::OnButtonSelected);
124 mButtonArea.Add(mButtonShow);
126 mButtonRefreshAlways = PushButton::New();
127 mButtonRefreshAlways.SetProperty(Button::Property::TOGGLABLE, true);
128 mButtonRefreshAlways.SetProperty(Toolkit::Button::Property::LABEL, "ALWAYS");
129 mButtonRefreshAlways.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
130 mButtonRefreshAlways.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
131 mButtonRefreshAlways.SetProperty(Actor::Property::SIZE, Vector2(windowSize.x / BUTTON_COUNT, BUTTON_HEIGHT));
132 mButtonRefreshAlways.SetProperty(Actor::Property::POSITION, Vector2((windowSize.x / BUTTON_COUNT) * 1.0f, 0.0f));
133 mButtonRefreshAlways.StateChangedSignal().Connect(this, &NativeImageSourceController::OnButtonSelected);
134 mButtonArea.Add(mButtonRefreshAlways);
136 mButtonRefreshOnce = PushButton::New();
137 mButtonRefreshOnce.SetProperty(Toolkit::Button::Property::LABEL, "ONCE");
138 mButtonRefreshOnce.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
139 mButtonRefreshOnce.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
140 mButtonRefreshOnce.SetProperty(Actor::Property::SIZE, Vector2(windowSize.x / BUTTON_COUNT, BUTTON_HEIGHT));
141 mButtonRefreshOnce.SetProperty(Actor::Property::POSITION, Vector2((windowSize.x / BUTTON_COUNT) * 2.0f, 0.0f));
142 mButtonRefreshOnce.ClickedSignal().Connect(this, &NativeImageSourceController::OnButtonSelected);
143 mButtonArea.Add(mButtonRefreshOnce);
145 mButtonCapture = PushButton::New();
146 mButtonCapture.SetProperty(Toolkit::Button::Property::LABEL, "CAPTURE");
147 mButtonCapture.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
148 mButtonCapture.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
149 mButtonCapture.SetProperty(Actor::Property::SIZE, Vector2(windowSize.x / BUTTON_COUNT, BUTTON_HEIGHT));
150 mButtonCapture.SetProperty(Actor::Property::POSITION, Vector2((windowSize.x / BUTTON_COUNT) * 3.0f, 0.0f));
151 mButtonCapture.ClickedSignal().Connect(this, &NativeImageSourceController::OnButtonSelected);
152 mButtonArea.Add(mButtonCapture);
154 mButtonReset = PushButton::New();
155 mButtonReset.SetProperty(Toolkit::Button::Property::LABEL, "RESET");
156 mButtonReset.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
157 mButtonReset.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
158 mButtonReset.SetProperty(Actor::Property::SIZE, Vector2(windowSize.x / BUTTON_COUNT, BUTTON_HEIGHT));
159 mButtonReset.SetProperty(Actor::Property::POSITION, Vector2((windowSize.x / BUTTON_COUNT) * 4.0f, 0.0f));
160 mButtonReset.ClickedSignal().Connect(this, &NativeImageSourceController::OnButtonSelected);
161 mButtonArea.Add(mButtonReset);
164 void CreateContentAreas()
166 Window window = mApplication.GetWindow();
167 Vector2 windowSize = window.GetSize();
169 float contentHeight((windowSize.y - BUTTON_HEIGHT) / 2.0f);
171 mTopContentArea = Actor::New();
172 mTopContentArea.SetProperty(Actor::Property::SIZE, Vector2(windowSize.x, contentHeight));
173 mTopContentArea.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_CENTER);
174 mTopContentArea.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_CENTER);
175 mTopContentArea.SetProperty(Actor::Property::POSITION_Y, BUTTON_HEIGHT);
176 window.Add(mTopContentArea);
178 mBottomContentArea = Actor::New();
179 mBottomContentArea.SetProperty(Actor::Property::SIZE, Vector2(windowSize.x, contentHeight));
180 mBottomContentArea.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::BOTTOM_CENTER);
181 mBottomContentArea.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::BOTTOM_CENTER);
182 window.Add(mBottomContentArea);
184 mSourceActor = ImageView::New(JPG_FILENAME);
185 mSourceActor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
186 mSourceActor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
187 mTopContentArea.Add(mSourceActor);
189 Animation animation = Animation::New(2.f);
190 Degree relativeRotationDegrees(90.0f);
191 Radian relativeRotationRadians(relativeRotationDegrees);
192 animation.AnimateTo(Property(mSourceActor, Actor::Property::ORIENTATION), Quaternion(relativeRotationRadians, Vector3::ZAXIS), AlphaFunction::LINEAR, TimePeriod(0.f, 0.5f));
193 animation.AnimateBy(Property(mSourceActor, Actor::Property::ORIENTATION), Quaternion(relativeRotationRadians, Vector3::ZAXIS), AlphaFunction::LINEAR, TimePeriod(0.5f, 0.5f));
194 animation.AnimateBy(Property(mSourceActor, Actor::Property::ORIENTATION), Quaternion(relativeRotationRadians, Vector3::ZAXIS), AlphaFunction::LINEAR, TimePeriod(1.f, 0.5f));
195 animation.AnimateBy(Property(mSourceActor, Actor::Property::ORIENTATION), Quaternion(relativeRotationRadians, Vector3::ZAXIS), AlphaFunction::LINEAR, TimePeriod(1.5f, 0.5f));
196 animation.SetLooping(true);
199 TextLabel textLabel1 = TextLabel::New("Image");
200 textLabel1.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::BOTTOM_CENTER);
201 textLabel1.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::BOTTOM_CENTER);
202 mTopContentArea.Add(textLabel1);
204 // Wait until button press before creating mOffscreenRenderTask
206 TextLabel textLabel2 = TextLabel::New("Native Image");
207 textLabel2.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::BOTTOM_CENTER);
208 textLabel2.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::BOTTOM_CENTER);
209 mBottomContentArea.Add(textLabel2);
212 void SetupNativeImage()
214 if(!mOffscreenRenderTask)
216 Window window = mApplication.GetWindow();
217 Vector2 windowSize = window.GetSize();
219 float contentHeight((windowSize.y - BUTTON_HEIGHT) / 2.0f);
220 Vector2 imageSize(windowSize.x, contentHeight);
222 mNativeImageSourcePtr = NativeImageSource::New(imageSize.width, imageSize.height, NativeImageSource::COLOR_DEPTH_DEFAULT);
223 mNativeTexture = Texture::New(*mNativeImageSourcePtr);
225 mFrameBuffer = FrameBuffer::New(mNativeTexture.GetWidth(), mNativeTexture.GetHeight(), FrameBuffer::Attachment::NONE);
226 mFrameBuffer.AttachColorTexture(mNativeTexture);
228 mCameraActor = CameraActor::New(imageSize);
229 mCameraActor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
230 mCameraActor.SetProperty(Actor::Property::PARENT_ORIGIN, AnchorPoint::CENTER);
231 mTopContentArea.Add(mCameraActor);
233 RenderTaskList taskList = window.GetRenderTaskList();
234 mOffscreenRenderTask = taskList.CreateTask();
235 mOffscreenRenderTask.SetSourceActor(mSourceActor);
236 mOffscreenRenderTask.SetClearColor(Color::WHITE);
237 mOffscreenRenderTask.SetClearEnabled(true);
238 mOffscreenRenderTask.SetCameraActor(mCameraActor);
239 mOffscreenRenderTask.GetCameraActor().SetInvertYAxis(true);
240 mOffscreenRenderTask.SetFrameBuffer(mFrameBuffer);
245 mOffscreenRenderTask.SetRefreshRate(RenderTask::REFRESH_ALWAYS);
249 mOffscreenRenderTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
253 void SetupDisplayActor(bool show)
259 // Make sure we have something to display
262 mDisplayActor = Actor::New();
263 mDisplayActor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
264 mDisplayActor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
266 Geometry geometry = DemoHelper::CreateTexturedQuad();
268 Shader shader = CreateShader(*mNativeImageSourcePtr);
270 Renderer renderer = Renderer::New(geometry, shader);
272 TextureSet textureSet = TextureSet::New();
273 textureSet.SetTexture(0u, mNativeTexture);
274 renderer.SetTextures(textureSet);
276 mDisplayActor.AddRenderer(renderer);
277 mDisplayActor.SetProperty(Actor::Property::SIZE, Vector2(mNativeTexture.GetWidth(), mNativeTexture.GetHeight()));
279 mBottomContentArea.Add(mDisplayActor);
284 UnparentAndReset(mDisplayActor);
290 mRefreshAlways = false;
293 mOffscreenRenderTask.FinishedSignal().Connect(this, &NativeImageSourceController::DoCapture);
296 void DoCapture(RenderTask& task)
298 task.FinishedSignal().Disconnect(this, &NativeImageSourceController::DoCapture);
300 mNativeImageSourcePtr->EncodeToFile(CAPTURE_FILENAME);
305 SetupDisplayActor(false);
307 Window window = mApplication.GetWindow();
308 RenderTaskList taskList = window.GetRenderTaskList();
309 taskList.RemoveTask(mOffscreenRenderTask);
310 mOffscreenRenderTask.Reset();
311 mCameraActor.Reset();
313 mFrameBuffer.Reset();
314 mNativeTexture.Reset();
315 mNativeImageSourcePtr.Reset();
318 bool OnButtonSelected(Toolkit::Button button)
320 Toolkit::PushButton pushButton = Toolkit::PushButton::DownCast(button);
322 if(pushButton == mButtonShow)
324 bool isSelected = mButtonShow.GetProperty(Toolkit::Button::Property::SELECTED).Get<bool>();
326 SetupDisplayActor(isSelected);
328 else if(pushButton == mButtonRefreshAlways)
330 bool isSelected = mButtonRefreshAlways.GetProperty(Toolkit::Button::Property::SELECTED).Get<bool>();
332 mRefreshAlways = isSelected;
335 else if(pushButton == mButtonRefreshOnce)
337 bool isSelected = mButtonRefreshAlways.GetProperty(Toolkit::Button::Property::SELECTED).Get<bool>();
341 mButtonRefreshAlways.SetProperty(Button::Property::SELECTED, false);
344 mRefreshAlways = false;
347 else if(pushButton == mButtonCapture)
351 else if(pushButton == mButtonReset)
359 void OnKeyEvent(const KeyEvent& event)
361 if(event.GetState() == KeyEvent::DOWN)
363 if(IsKey(event, Dali::DALI_KEY_ESCAPE) || IsKey(event, Dali::DALI_KEY_BACK))
371 Application& mApplication;
374 Actor mTopContentArea;
375 Actor mBottomContentArea;
377 PushButton mButtonShow;
378 PushButton mButtonRefreshAlways;
379 PushButton mButtonRefreshOnce;
380 PushButton mButtonCapture;
381 PushButton mButtonReset;
385 NativeImageSourcePtr mNativeImageSourcePtr;
386 Texture mNativeTexture;
387 FrameBuffer mFrameBuffer;
389 RenderTask mOffscreenRenderTask;
390 CameraActor mCameraActor;
397 int DALI_EXPORT_API main(int argc, char** argv)
399 Application application = Application::New(&argc, &argv);
400 NativeImageSourceController test(application);
401 application.MainLoop();