From 39028190b336a1a329f9cf7bccad86fe2f096373 Mon Sep 17 00:00:00 2001 From: David Steele Date: Fri, 24 Nov 2023 15:43:55 +0000 Subject: [PATCH] [Tizen] Added 2d physics benchmark First 30s, runs N balls using Animation & property notification that don't interact, Second 30s, runs N balls using 2D Physics and collisions. N by default is 500, but can be changed on the command line. FPS tracking is automatically switched on for this benchmark (Also changed CMakeLists.txt to be able to work as a subdirectory in a multi-repo build) Change-Id: Iccee1d40650563e3f45e021b4fb3fff871cc393e --- build/tizen/CMakeLists.txt | 4 +- com.samsung.dali-demo.xml | 3 + examples/benchmark-2dphysics/README.md | 13 + .../benchmark-2d-physics-controller.cpp | 406 +++++++++++++++++++++ examples/benchmark-2dphysics/dependencies.cmake | 5 + resources/po/en_GB.po | 3 + resources/po/en_US.po | 3 + shared/dali-demo-strings.h | 2 + tests-reel/dali-tests-reel.cpp | 1 + 9 files changed, 438 insertions(+), 2 deletions(-) create mode 100644 examples/benchmark-2dphysics/README.md create mode 100644 examples/benchmark-2dphysics/benchmark-2d-physics-controller.cpp create mode 100644 examples/benchmark-2dphysics/dependencies.cmake diff --git a/build/tizen/CMakeLists.txt b/build/tizen/CMakeLists.txt index 5270d57..68e3ca2 100644 --- a/build/tizen/CMakeLists.txt +++ b/build/tizen/CMakeLists.txt @@ -21,8 +21,8 @@ OPTION(ENABLE_TRACE "Enable Trace" OFF) OPTION(ENABLE_PKG_CONFIGURE "Use pkgconfig" ON) OPTION(INTERNATIONALIZATION "Internationalization demo string names" ON) -SET(ROOT_SRC_DIR ${CMAKE_SOURCE_DIR}/../..) -SET(DEMO_SHARED ${CMAKE_SOURCE_DIR}/../../shared) +SET(ROOT_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../..) +SET(DEMO_SHARED ${CMAKE_CURRENT_SOURCE_DIR}/../../shared) SET(PREFIX ${CMAKE_INSTALL_PREFIX}) diff --git a/com.samsung.dali-demo.xml b/com.samsung.dali-demo.xml index 59fceae..4c95b90 100644 --- a/com.samsung.dali-demo.xml +++ b/com.samsung.dali-demo.xml @@ -43,6 +43,9 @@ + + + diff --git a/examples/benchmark-2dphysics/README.md b/examples/benchmark-2dphysics/README.md new file mode 100644 index 0000000..9fc5712 --- /dev/null +++ b/examples/benchmark-2dphysics/README.md @@ -0,0 +1,13 @@ +# 2d Physics benchmark Example + +This is an example to test the performance of DALI with and without physics enabled. +It first measures performance with physics and collisions off, by animating motion using +property notifications for 30 seconds. Uses N ImageViews, where N defaults to 500 + +Then, it creates a PhysicsAdaptor and uses zero gravity and a bounding box to achieve a +similar visual result with N ImageViews attached to physics bodies. + +N can be changed on the command line. + + + diff --git a/examples/benchmark-2dphysics/benchmark-2d-physics-controller.cpp b/examples/benchmark-2dphysics/benchmark-2d-physics-controller.cpp new file mode 100644 index 0000000..2926d5c --- /dev/null +++ b/examples/benchmark-2dphysics/benchmark-2d-physics-controller.cpp @@ -0,0 +1,406 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +using namespace Dali; +using namespace Dali::Toolkit::Physics; +using namespace Dali::ParentOrigin; +using namespace Dali::AnchorPoint; + +#if defined(DEBUG_ENABLED) +Debug::Filter* gPhysicsDemo = Debug::Filter::New(Debug::Concise, false, "LOG_PHYSICS_EXAMPLE"); +#endif + +const float MAX_ANIMATION_DURATION{60.0f}; +const uint32_t ANIMATION_TIME{30000}; +const uint32_t DEFAULT_BALL_COUNT{500}; + +#if defined(_ARCH_ARM_) +#define DEMO_ICON_DIR "/usr/share/icons" +#else +#define DEMO_ICON_DIR DEMO_IMAGE_DIR +#endif + +const std::string BALL_IMAGES[] = {DEMO_IMAGE_DIR "/blocks-ball.png", + DEMO_ICON_DIR "/dali-tests.png", + DEMO_ICON_DIR "/dali-examples.png", + DEMO_ICON_DIR "/com.samsung.dali-demo.png"}; + +const Vector2 BALL_SIZE{26.0f, 26.0f}; + +// Groups that can collide with each other: +const cpGroup BALL_GROUP{1 << 0}; +const cpGroup BOUNDS_GROUP{1 << 1}; + +const cpBitmask COLLISION_MASK{0xfF}; + +const cpBitmask BALL_COLLIDES_WITH{BALL_GROUP | BOUNDS_GROUP}; + +/** + * @brief The physics demo using Chipmunk2D APIs. + */ +class Physics2dBenchmarkController : public ConnectionTracker +{ +public: + Physics2dBenchmarkController(Application& app, int numberOfBalls) + : mApplication(app), + mBallNumber(numberOfBalls) + { + app.InitSignal().Connect(this, &Physics2dBenchmarkController::OnInit); + app.TerminateSignal().Connect(this, &Physics2dBenchmarkController::OnTerminate); + } + + ~Physics2dBenchmarkController() = default; + + void OnInit(Application& application) + { + mWindow = application.GetWindow(); + mWindow.ResizeSignal().Connect(this, &Physics2dBenchmarkController::OnWindowResize); + mWindow.KeyEventSignal().Connect(this, &Physics2dBenchmarkController::OnKeyEv); + mWindow.GetRootLayer().TouchedSignal().Connect(this, &Physics2dBenchmarkController::OnTouched); + mWindow.SetBackgroundColor(Color::DARK_SLATE_GRAY); + + CreateAnimationSimulation(); + + mTimer = Timer::New(ANIMATION_TIME); + mTimer.TickSignal().Connect(this, &Physics2dBenchmarkController::AnimationSimFinished); + mTimer.Start(); + } + + void CreateAnimationSimulation() + { + Window::WindowSize windowSize = mWindow.GetSize(); + mBallActors.resize(mBallNumber); + mBallVelocity.resize(mBallNumber); + + mAnimationSimRootActor = Layer::New(); + mAnimationSimRootActor.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS); + mAnimationSimRootActor[Actor::Property::PARENT_ORIGIN] = Dali::ParentOrigin::CENTER; + mAnimationSimRootActor[Actor::Property::ANCHOR_POINT] = Dali::AnchorPoint::CENTER; + + mWindow.Add(mAnimationSimRootActor); + std::ostringstream oss; + oss << "Animation simulation of " << mBallNumber << " balls"; + auto title = Toolkit::TextLabel::New(oss.str()); + mAnimationSimRootActor.Add(title); + title[Toolkit::TextLabel::Property::TEXT_COLOR] = Color::WHITE; + title[Actor::Property::PARENT_ORIGIN] = Dali::ParentOrigin::TOP_CENTER; + title[Actor::Property::ANCHOR_POINT] = Dali::AnchorPoint::TOP_CENTER; + title[Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT] = HorizontalAlignment::CENTER; + title.SetResizePolicy(ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS); + + const float margin(BALL_SIZE.width * 0.5f); + + for(int i = 0; i < mBallNumber; ++i) + { + Actor ball = mBallActors[i] = Toolkit::ImageView::New(BALL_IMAGES[rand() % 4]); + ball[Actor::Property::PARENT_ORIGIN] = Dali::ParentOrigin::CENTER; + ball[Actor::Property::ANCHOR_POINT] = Dali::AnchorPoint::CENTER; + + ball[Actor::Property::NAME] = "Ball"; + ball[Actor::Property::SIZE] = BALL_SIZE; // Halve the image size + int width = windowSize.GetWidth() / 2; + int height = windowSize.GetHeight() / 2; + ball[Actor::Property::POSITION] = Vector3(Random::Range(margin - width, width - margin), Random::Range(margin - height, height - margin), 0.0f); + ball.RegisterProperty("index", i); + mAnimationSimRootActor.Add(ball); + + mBallVelocity[i] = Vector3(Random::Range(-25.0f, 25.0f), Random::Range(-25.0f, 25.0f), 0.0f); + mBallVelocity[i].Normalize(); + mBallVelocity[i] = mBallVelocity[i] * Random::Range(15.0f, 50.0f); + + PropertyNotification leftNotify = mBallActors[i].AddPropertyNotification(Actor::Property::POSITION_X, LessThanCondition(margin - width)); + leftNotify.NotifySignal().Connect(this, &Physics2dBenchmarkController::OnHitLeftWall); + + PropertyNotification rightNotify = mBallActors[i].AddPropertyNotification(Actor::Property::POSITION_X, GreaterThanCondition(width - margin)); + rightNotify.NotifySignal().Connect(this, &Physics2dBenchmarkController::OnHitRightWall); + + PropertyNotification topNotify = mBallActors[i].AddPropertyNotification(Actor::Property::POSITION_Y, LessThanCondition(margin - height)); + topNotify.NotifySignal().Connect(this, &Physics2dBenchmarkController::OnHitTopWall); + + PropertyNotification bottomNotify = mBallActors[i].AddPropertyNotification(Actor::Property::POSITION_Y, GreaterThanCondition(height - margin)); + bottomNotify.NotifySignal().Connect(this, &Physics2dBenchmarkController::OnHitBottomWall); + } + + title.RaiseToTop(); + ContinueAnimation(); + } + + bool AnimationSimFinished() + { + static bool first = true; + if(first) + { + UnparentAndReset(mAnimationSimRootActor); + mBallAnimation.Stop(); + mBallAnimation.Clear(); + first = false; + + CreatePhysicsSimulation(); + return true; + } + + mApplication.Quit(); + return false; + } + + void ContinueAnimation() + { + if(mBallAnimation) + { + mBallAnimation.Clear(); + } + mBallAnimation = Animation::New(MAX_ANIMATION_DURATION); + for(int i = 0; i < mBallNumber; ++i) + { + mBallAnimation.AnimateBy(Property(mBallActors[i], Actor::Property::POSITION), mBallVelocity[i] * MAX_ANIMATION_DURATION); + } + mBallAnimation.Play(); + } + + void OnHitLeftWall(PropertyNotification& source) + { + auto actor = Actor::DownCast(source.GetTarget()); + if(actor) + { + int index = actor["index"]; + mBallVelocity[index].x = fabsf(mBallVelocity[index].x); + ContinueAnimation(); + } + } + + void OnHitRightWall(PropertyNotification& source) + { + auto actor = Actor::DownCast(source.GetTarget()); + if(actor) + { + int index = actor["index"]; + mBallVelocity[index].x = -fabsf(mBallVelocity[index].x); + ContinueAnimation(); + } + } + + void OnHitBottomWall(PropertyNotification& source) + { + auto actor = Actor::DownCast(source.GetTarget()); + if(actor) + { + int index = actor["index"]; + mBallVelocity[index].y = -fabsf(mBallVelocity[index].y); + ContinueAnimation(); + } + } + + void OnHitTopWall(PropertyNotification& source) + { + auto actor = Actor::DownCast(source.GetTarget()); + if(actor) + { + int index = actor["index"]; + mBallVelocity[index].y = fabsf(mBallVelocity[index].y); + ContinueAnimation(); + } + } + + void CreatePhysicsSimulation() + { + Window::WindowSize windowSize = mWindow.GetSize(); + + // Map Physics space (origin bottom left, +ve Y up) + // to DALi space (origin center, +ve Y down) + mPhysicsTransform.SetIdentityAndScale(Vector3(1.0f, -1.0f, 1.0f)); + mPhysicsTransform.SetTranslation(Vector3(windowSize.GetWidth() * 0.5f, + windowSize.GetHeight() * 0.5f, + 0.0f)); + + mPhysicsAdaptor = PhysicsAdaptor::New(mPhysicsTransform, windowSize); + mPhysicsRoot = mPhysicsAdaptor.GetRootActor(); + mWindow.Add(mPhysicsRoot); + + auto scopedAccessor = mPhysicsAdaptor.GetPhysicsAccessor(); + cpSpace* space = scopedAccessor->GetNative().Get(); + cpSpaceSetGravity(space, cpv(0, 0)); + + CreateBounds(space, windowSize); + + for(int i = 0; i < mBallNumber; ++i) + { + mBalls.push_back(CreateBall(space)); + } + + // Process any async queued methods next frame + mPhysicsAdaptor.CreateSyncPoint(); + + std::ostringstream oss; + oss << "Physics simulation of " << mBallNumber << " balls"; + auto title = Toolkit::TextLabel::New(oss.str()); + mPhysicsRoot.Add(title); + title[Toolkit::TextLabel::Property::TEXT_COLOR] = Color::WHITE; + title[Actor::Property::PARENT_ORIGIN] = Dali::ParentOrigin::TOP_CENTER; + title[Actor::Property::ANCHOR_POINT] = Dali::AnchorPoint::TOP_CENTER; + title[Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT] = HorizontalAlignment::CENTER; + title.SetResizePolicy(ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS); + title.RaiseToTop(); + } + + PhysicsActor CreateBall(cpSpace* space) + { + const float BALL_MASS = 10.0f; + const float BALL_RADIUS = BALL_SIZE.x * 0.25f; + const float BALL_ELASTICITY = 1.0f; + const float BALL_FRICTION = 0.0f; + + auto ball = Toolkit::ImageView::New(BALL_IMAGES[rand() % 4]); + ball[Actor::Property::NAME] = "Ball"; + ball[Actor::Property::SIZE] = BALL_SIZE * 0.5f; + cpBody* body = cpSpaceAddBody(space, cpBodyNew(BALL_MASS, cpMomentForCircle(BALL_MASS, 0.0f, BALL_RADIUS, cpvzero))); + + cpShape* shape = cpSpaceAddShape(space, cpCircleShapeNew(body, BALL_RADIUS, cpvzero)); + cpShapeSetElasticity(shape, BALL_ELASTICITY); + cpShapeSetFriction(shape, BALL_FRICTION); + + PhysicsActor physicsBall = mPhysicsAdaptor.AddActorBody(ball, body); + + Window::WindowSize windowSize = mWindow.GetSize(); + + const float fw = 0.5f * (windowSize.GetWidth() - BALL_RADIUS); + const float fh = 0.5f * (windowSize.GetHeight() - BALL_RADIUS); + + // Example of setting physics property on update thread + physicsBall.AsyncSetPhysicsPosition(Vector3(Random::Range(-fw, fw), Random::Range(-fh, -fh * 0.5), 0.0f)); + + // Example of queuing a chipmunk method to run on the update thread + mPhysicsAdaptor.Queue([body]() { + cpBodySetVelocity(body, cpv(Random::Range(-100.0, 100.0), Random::Range(-100.0, 100.0))); + }); + return physicsBall; + } + + void CreateBounds(cpSpace* space, Window::WindowSize size) + { + // We're working in physics space here - coords are: origin: bottom left, +ve Y: up + int32_t xBound = static_cast(static_cast(size.GetWidth())); + int32_t yBound = static_cast(static_cast(size.GetHeight())); + + cpBody* staticBody = cpSpaceGetStaticBody(space); + + if(mLeftBound) + { + cpSpaceRemoveShape(space, mLeftBound); + cpSpaceRemoveShape(space, mRightBound); + cpSpaceRemoveShape(space, mTopBound); + cpSpaceRemoveShape(space, mBottomBound); + cpShapeFree(mLeftBound); + cpShapeFree(mRightBound); + cpShapeFree(mTopBound); + cpShapeFree(mBottomBound); + } + mLeftBound = AddBound(space, staticBody, cpv(0, 0), cpv(0, yBound)); + mRightBound = AddBound(space, staticBody, cpv(xBound, 0), cpv(xBound, yBound)); + mTopBound = AddBound(space, staticBody, cpv(0, 0), cpv(xBound, 0)); + mBottomBound = AddBound(space, staticBody, cpv(0, yBound), cpv(xBound, yBound)); + } + + cpShape* AddBound(cpSpace* space, cpBody* staticBody, cpVect start, cpVect end) + { + cpShape* shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, start, end, 0.0f)); + cpShapeSetElasticity(shape, 1.0f); + cpShapeSetFriction(shape, 1.0f); + + cpShapeSetFilter(shape, cpShapeFilterNew(BOUNDS_GROUP, COLLISION_MASK, COLLISION_MASK)); + return shape; + } + + void OnTerminate(Application& application) + { + UnparentAndReset(mPhysicsRoot); + } + + void OnWindowResize(Window window, Window::WindowSize newSize) + { + auto scopedAccessor = mPhysicsAdaptor.GetPhysicsAccessor(); + cpSpace* space = scopedAccessor->GetNative().Get(); + + CreateBounds(space, newSize); + } + + bool OnTouched(Dali::Actor actor, const Dali::TouchEvent& touch) + { + mApplication.Quit(); + return false; + } + + void OnKeyEv(const Dali::KeyEvent& event) + { + if(event.GetState() == KeyEvent::DOWN) + { + if(IsKey(event, Dali::DALI_KEY_ESCAPE) || IsKey(event, Dali::DALI_KEY_BACK)) + { + mApplication.Quit(); + } + } + } + +private: + Application& mApplication; + Window mWindow; + + PhysicsAdaptor mPhysicsAdaptor; + std::vector mBalls; + Matrix mPhysicsTransform; + Actor mPhysicsRoot; + Layer mPhysicsDebugLayer; + Layer mAnimationSimRootActor; + cpShape* mLeftBound{nullptr}; + cpShape* mRightBound{nullptr}; + cpShape* mTopBound{nullptr}; + cpShape* mBottomBound{nullptr}; + + std::vector mBallActors; + std::vector mBallVelocity; + int mBallNumber; + Animation mBallAnimation; + Timer mTimer; +}; + +int DALI_EXPORT_API main(int argc, char** argv) +{ + setenv("DALI_FPS_TRACKING", "5", 1); + Application application = Application::New(&argc, &argv); + + int numberOfBalls = DEFAULT_BALL_COUNT; + if(argc > 1) + { + numberOfBalls = atoi(argv[1]); + } + + Physics2dBenchmarkController controller(application, numberOfBalls); + application.MainLoop(); + return 0; +} diff --git a/examples/benchmark-2dphysics/dependencies.cmake b/examples/benchmark-2dphysics/dependencies.cmake new file mode 100644 index 0000000..b30b385 --- /dev/null +++ b/examples/benchmark-2dphysics/dependencies.cmake @@ -0,0 +1,5 @@ +TARGET_COMPILE_OPTIONS(${EXAMPLE}.example PUBLIC ${DALI_PHYSICS_2D_CFLAGS}) +TARGET_LINK_LIBRARIES(${EXAMPLE}.example ${DALI_PHYSICS_2D_LDFLAGS}) +MESSAGE(STATUS "Included dependencies for ${EXAMPLE}") +MESSAGE(STATUS " Compile options: ${DALI_PHYSICS_2D_CFLAGS}") +MESSAGE(STATUS " Link options: ${DALI_PHYSICS_2D_LDFLAGS}") diff --git a/resources/po/en_GB.po b/resources/po/en_GB.po index ad38e07..30178dc 100755 --- a/resources/po/en_GB.po +++ b/resources/po/en_GB.po @@ -16,6 +16,9 @@ msgstr "Basic Light" msgid "DALI_DEMO_STR_TITLE_BENCHMARK" msgstr "ImageView Benchmark" +msgid "DALI_DEMO_STR_TITLE_BENCHMARK_2D_PHYSICS" +msgstr "2D Physics Benchmark" + msgid "DALI_DEMO_STR_TITLE_BEZIER_CURVE" msgstr "Bezier Curve" diff --git a/resources/po/en_US.po b/resources/po/en_US.po index 7c96551..52592cd 100755 --- a/resources/po/en_US.po +++ b/resources/po/en_US.po @@ -16,6 +16,9 @@ msgstr "Basic Light" msgid "DALI_DEMO_STR_TITLE_BENCHMARK" msgstr "ImageView Benchmark" +msgid "DALI_DEMO_STR_TITLE_BENCHMARK_2D_PHYSICS" +msgstr "2D Physics Benchmark" + msgid "DALI_DEMO_STR_TITLE_BEZIER_CURVE" msgstr "Bezier Curve" diff --git a/shared/dali-demo-strings.h b/shared/dali-demo-strings.h index 90e16f1..3346db7 100644 --- a/shared/dali-demo-strings.h +++ b/shared/dali-demo-strings.h @@ -41,6 +41,7 @@ extern "C" #define DALI_DEMO_STR_TITLE_ARC_VISUAL dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_ARC_VISUAL") #define DALI_DEMO_STR_TITLE_BASIC_LIGHT dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_BASIC_LIGHT") #define DALI_DEMO_STR_TITLE_BENCHMARK dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_BENCHMARK") +#define DALI_DEMO_STR_TITLE_BENCHMARK_2D_PHYSICS dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_BENCHMARK_2D_PHYSICS") #define DALI_DEMO_STR_TITLE_BEZIER_CURVE dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_BEZIER_CURVE") #define DALI_DEMO_STR_TITLE_BLOCKS dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_BLOCKS") #define DALI_DEMO_STR_TITLE_BLOOM_VIEW dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_BLOOM_VIEW") @@ -163,6 +164,7 @@ extern "C" #define DALI_DEMO_STR_TITLE_ARC_VISUAL "Arc Visual" #define DALI_DEMO_STR_TITLE_BASIC_LIGHT "Basic Light" #define DALI_DEMO_STR_TITLE_BENCHMARK "ImageView Benchmark" +#define DALI_DEMO_STR_TITLE_BENCHMARK_2D_PHYSICS "2D Physics Benchmark" #define DALI_DEMO_STR_TITLE_BEZIER_CURVE "Alpha Function Bezier Curve" #define DALI_DEMO_STR_TITLE_BLOCKS "Blocks" #define DALI_DEMO_STR_TITLE_BLOOM_VIEW "Bloom" diff --git a/tests-reel/dali-tests-reel.cpp b/tests-reel/dali-tests-reel.cpp index 8dfd6ff..5d2d3c4 100644 --- a/tests-reel/dali-tests-reel.cpp +++ b/tests-reel/dali-tests-reel.cpp @@ -38,6 +38,7 @@ int DALI_EXPORT_API main(int argc, char** argv) DaliTableView demo(app); demo.AddExample(Example("benchmark.example", DALI_DEMO_STR_TITLE_BENCHMARK)); + demo.AddExample(Example("benchmark-2dphysics.example", DALI_DEMO_STR_TITLE_BENCHMARK_2D_PHYSICS)); demo.AddExample(Example("camera-test.example", DALI_DEMO_STR_TITLE_CAMERA_TEST)); demo.AddExample(Example("compressed-texture-formats.example", DALI_DEMO_STR_TITLE_COMPRESSED_TEXTURE_FORMATS)); demo.AddExample(Example("homescreen-benchmark.example", DALI_DEMO_STR_TITLE_HOMESCREEN)); -- 2.7.4