void TestApplication::Initialize()
{
+ // We always need the first update!
+ mStatus.keepUpdating = Integration::KeepUpdating::STAGE_KEEP_RENDERING;
+
mCore = Dali::Integration::Core::New(
mRenderController,
mPlatformAbstraction,
void TestApplication::DoUpdate( unsigned int intervalMilliseconds )
{
+ if( GetUpdateStatus() == 0 &&
+ mRenderStatus.NeedsUpdate() == false &&
+ ! GetRenderController().WasCalled(TestRenderController::RequestUpdateFunc) )
+ {
+ fprintf(stderr, "WARNING - Update not required\n");
+ }
+
unsigned int nextVSyncTime = mLastVSyncTime + intervalMilliseconds;
float elapsedSeconds = intervalMilliseconds / 1e3f;
mCore->Update( elapsedSeconds, mLastVSyncTime, nextVSyncTime, mStatus );
+ GetRenderController().Initialize();
+
mLastVSyncTime = nextVSyncTime;
}
return mStatus.KeepUpdating();
}
+bool TestApplication::GetRenderNeedsUpdate()
+{
+ return mRenderStatus.NeedsUpdate();
+}
+bool TestApplication::GetRenderHasRendered()
+{
+ return mRenderStatus.HasRendered();
+}
+
bool TestApplication::RenderOnly( )
{
// Update Time values
bool UpdateOnly( unsigned int intervalMilliseconds = DEFAULT_RENDER_INTERVAL );
bool RenderOnly( );
void ResetContext();
+ bool GetRenderNeedsUpdate();
+ bool GetRenderHasRendered();
private:
void DoUpdate( unsigned int intervalMilliseconds );
*/
TraceCallStack& TestGlSyncAbstraction::GetTrace() { return mTrace; }
+int TestGlSyncAbstraction::GetNumberOfSyncObjects()
+{
+ return mSyncObjects.size();
+}
+
} // Dali
*/
TraceCallStack& GetTrace();
+ /**
+ * Get the number of sync objects
+ *
+ * @return the number of sync objects
+ */
+ int GetNumberOfSyncObjects();
+
private:
typedef std::vector<TestSyncObject*> SyncContainer;
typedef SyncContainer::iterator SyncIter;
TestNativeImage::TestNativeImage(int width, int height)
: mWidth(width), mHeight(height), mExtensionCreateCalls(0), mExtensionDestroyCalls(0), mTargetTextureCalls(0)
{
+ mExtension = new TestNativeImageExtension();
}
TestNativeImage::~TestNativeImage()
// INTERNAL INCLUDES
#include <dali/public-api/images/native-image-interface.h>
+#include <dali/devel-api/images/native-image-interface-extension.h>
namespace Dali
{
class TestNativeImage;
typedef IntrusivePtr<TestNativeImage> TestNativeImagePointer;
+class DALI_IMPORT_API TestNativeImageExtension: public Dali::NativeImageInterface::Extension
+{
+public:
+ inline const char* GetCustomFragmentPreFix(){return "#extension GL_OES_EGL_image_external:require\n";}
+ inline const char* GetCustomSamplerTypename(){return "samplerExternalOES";}
+
+};
+
class DALI_IMPORT_API TestNativeImage : public Dali::NativeImageInterface
{
public:
inline virtual unsigned int GetWidth() const {return mWidth;};
inline virtual unsigned int GetHeight() const {return mHeight;};
inline virtual bool RequiresBlending() const {return true;};
+ inline virtual Dali::NativeImageInterface::Extension* GetExtension() {return mExtension;}
private:
TestNativeImage(int width, int height);
int mExtensionCreateCalls;
int mExtensionDestroyCalls;
int mTargetTextureCalls;
+ TestNativeImageExtension* mExtension;
};
} // Dali
END_TEST;
}
+int UtcDaliAnimationSetLoopCountP(void)
+{
+ TestApplication application;
+
+ Actor actor = Actor::New();
+ Stage::GetCurrent().Add(actor);
+
+ // Build the animation
+ float durationSeconds(1.0f);
+ Animation animation = Animation::New(durationSeconds);
+ Vector3 targetPosition(10.0f, 10.0f, 10.0f);
+ animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR);
+
+ // Start the animation
+ animation.SetLoopCount(3);
+ DALI_TEST_CHECK(animation.IsLooping());
+ animation.Play();
+
+ bool signalReceived(false);
+ AnimationFinishCheck finishCheck(signalReceived);
+ animation.FinishedSignal().Connect(&application, finishCheck);
+
+ application.Render(0);
+ application.SendNotification();
+ application.Render(0);
+ application.SendNotification();
+ application.Render(0);
+ application.SendNotification();
+ application.Render(0);
+ application.SendNotification();
+
+ // Loop
+ float intervalSeconds = 3.0f;
+
+ application.Render(static_cast<unsigned int>(durationSeconds*intervalSeconds*1000.0f));
+ application.Render(static_cast<unsigned int>(durationSeconds*intervalSeconds*1000.0f));
+
+ application.Render(0);
+ application.SendNotification();
+ application.Render(0);
+ application.SendNotification();
+ application.Render(0);
+ application.SendNotification();
+ application.Render(0);
+ application.SendNotification();
+ finishCheck.CheckSignalNotReceived();
+
+ application.Render(static_cast<unsigned int>(durationSeconds*intervalSeconds*1000.0f));
+
+ application.SendNotification();
+ finishCheck.CheckSignalReceived();
+ DALI_TEST_EQUALS( targetPosition, actor.GetCurrentPosition(), TEST_LOCATION );
+
+ finishCheck.Reset();
+
+ application.Render(static_cast<unsigned int>(durationSeconds*intervalSeconds*1000.0f));
+ application.SendNotification();
+ finishCheck.CheckSignalNotReceived();
+
+ application.Render(static_cast<unsigned int>(durationSeconds*intervalSeconds*1000.0f));
+ application.Render(static_cast<unsigned int>(durationSeconds*intervalSeconds*1000.0f));
+ application.Render(static_cast<unsigned int>(durationSeconds*intervalSeconds*1000.0f));
+ application.Render(static_cast<unsigned int>(durationSeconds*intervalSeconds*1000.0f));
+ application.SendNotification();
+ finishCheck.CheckSignalNotReceived();
+
+ END_TEST;
+}
+
+int UtcDaliAnimationSetLoopCountP2(void)
+{
+ TestApplication application;
+
+ //
+ // switching between forever and loop count
+ //
+
+ Actor actor = Actor::New();
+ Stage::GetCurrent().Add(actor);
+
+ // Build the animation
+ float durationSeconds(1.0f);
+ Animation animation = Animation::New(durationSeconds);
+ Vector3 targetPosition(10.0f, 10.0f, 10.0f);
+ animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR);
+ animation.SetEndAction(Animation::Discard);
+
+ // Start the animation
+ animation.SetLoopCount(3);
+ DALI_TEST_CHECK(animation.IsLooping());
+ animation.Play();
+
+ bool signalReceived(false);
+ AnimationFinishCheck finishCheck(signalReceived);
+ animation.FinishedSignal().Connect(&application, finishCheck);
+
+ float intervalSeconds = 3.0f;
+
+ application.SendNotification();
+ application.Render(static_cast<unsigned int>(durationSeconds*intervalSeconds*1000.0f));
+ application.SendNotification();
+ application.Render(static_cast<unsigned int>(durationSeconds*intervalSeconds*1000.0f));
+ application.SendNotification();
+ application.Render(static_cast<unsigned int>(durationSeconds*intervalSeconds*1000.0f));
+ application.SendNotification();
+
+ application.SendNotification();
+ finishCheck.CheckSignalReceived();
+
+ finishCheck.Reset();
+
+ // Loop forever
+ animation.SetLooping(true);
+ DALI_TEST_CHECK(animation.IsLooping());
+
+ application.Render(static_cast<unsigned int>(durationSeconds*intervalSeconds*1000.0f));
+ application.SendNotification();
+ finishCheck.CheckSignalNotReceived();
+
+ application.Render(static_cast<unsigned int>(durationSeconds*intervalSeconds*1000.0f));
+ application.SendNotification();
+ application.Render(static_cast<unsigned int>(durationSeconds*intervalSeconds*1000.0f));
+ application.SendNotification();
+ application.Render(static_cast<unsigned int>(durationSeconds*intervalSeconds*1000.0f));
+ application.SendNotification();
+ application.Render(static_cast<unsigned int>(durationSeconds*intervalSeconds*1000.0f));
+ application.SendNotification();
+ application.SendNotification();
+ finishCheck.CheckSignalNotReceived();
+
+ finishCheck.Reset();
+
+ // Loop N again
+ animation.SetLoopCount(3);
+ DALI_TEST_CHECK(animation.IsLooping());
+ animation.Play();
+
+ application.SendNotification();
+ application.Render(static_cast<unsigned int>(durationSeconds*intervalSeconds*1000.0f));
+ application.SendNotification();
+ application.Render(static_cast<unsigned int>(durationSeconds*intervalSeconds*1000.0f));
+ application.SendNotification();
+ finishCheck.CheckSignalNotReceived();
+
+ application.Render(static_cast<unsigned int>(durationSeconds*intervalSeconds*1000.0f));
+ application.SendNotification();
+ finishCheck.CheckSignalReceived();
+
+ finishCheck.Reset();
+
+ // loop forever
+ animation.SetLooping(true);
+ DALI_TEST_CHECK(animation.IsLooping());
+
+ application.Render(static_cast<unsigned int>(durationSeconds*intervalSeconds*1000.0f));
+ application.SendNotification();
+ finishCheck.CheckSignalNotReceived();
+
+ application.Render(static_cast<unsigned int>(durationSeconds*intervalSeconds*1000.0f));
+ application.SendNotification();
+ application.Render(static_cast<unsigned int>(durationSeconds*intervalSeconds*1000.0f));
+ application.SendNotification();
+ application.Render(static_cast<unsigned int>(durationSeconds*intervalSeconds*1000.0f));
+ application.SendNotification();
+ application.Render(static_cast<unsigned int>(durationSeconds*intervalSeconds*1000.0f));
+ application.SendNotification();
+ finishCheck.CheckSignalNotReceived();
+
+ finishCheck.Reset();
+
+ // Loop N again
+ animation.SetLoopCount(3);
+ DALI_TEST_CHECK(animation.IsLooping());
+
+ application.SendNotification();
+ application.Render(static_cast<unsigned int>(durationSeconds*intervalSeconds*1000.0f));
+ application.SendNotification();
+ application.Render(static_cast<unsigned int>(durationSeconds*intervalSeconds*1000.0f));
+ application.SendNotification();
+ finishCheck.CheckSignalNotReceived();
+
+ application.Render(static_cast<unsigned int>(durationSeconds*intervalSeconds*1000.0f));
+ application.SendNotification();
+ finishCheck.CheckSignalNotReceived(); // we never hit play
+
+ finishCheck.Reset();
+
+
+ END_TEST;
+}
+
+int UtcDaliAnimationSetLoopCountP3(void)
+{
+ TestApplication application;
+
+ //
+ // switching between forever and loop count
+ //
+ Actor actor = Actor::New();
+ Stage::GetCurrent().Add(actor);
+
+ // Build the animation
+ float durationSeconds(1.0f);
+ Animation animation = Animation::New(durationSeconds);
+ Vector3 targetPosition(10.0f, 10.0f, 10.0f);
+ animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR);
+ animation.SetEndAction(Animation::Discard);
+
+ float intervalSeconds = 3.0f;
+
+ bool signalReceived(false);
+ AnimationFinishCheck finishCheck(signalReceived);
+ animation.FinishedSignal().Connect(&application, finishCheck);
+
+ // loop forever
+ animation.SetLooping(true);
+ DALI_TEST_CHECK(animation.IsLooping());
+
+ application.Render(static_cast<unsigned int>(durationSeconds*intervalSeconds*1000.0f));
+ application.SendNotification();
+ finishCheck.CheckSignalNotReceived();
+
+ application.Render(static_cast<unsigned int>(durationSeconds*intervalSeconds*1000.0f));
+ application.SendNotification();
+ application.Render(static_cast<unsigned int>(durationSeconds*intervalSeconds*1000.0f));
+ application.SendNotification();
+ application.Render(static_cast<unsigned int>(durationSeconds*intervalSeconds*1000.0f));
+ application.SendNotification();
+ application.Render(static_cast<unsigned int>(durationSeconds*intervalSeconds*1000.0f));
+ application.SendNotification();
+ finishCheck.CheckSignalNotReceived();
+
+ finishCheck.Reset();
+
+ // Loop N again
+ animation.SetLoopCount(3);
+ DALI_TEST_CHECK(animation.IsLooping());
+
+ application.SendNotification();
+ application.Render(static_cast<unsigned int>(durationSeconds*intervalSeconds*1000.0f));
+ application.SendNotification();
+ application.Render(static_cast<unsigned int>(durationSeconds*intervalSeconds*1000.0f));
+ application.SendNotification();
+ finishCheck.CheckSignalNotReceived();
+
+ application.Render(static_cast<unsigned int>(durationSeconds*intervalSeconds*1000.0f));
+ application.SendNotification();
+ finishCheck.CheckSignalNotReceived(); // we never hit play
+
+ finishCheck.Reset();
+
+
+ END_TEST;
+}
+
+int UtcDaliAnimationSetLoopCountP4(void)
+{
+ TestApplication application;
+
+ //
+ // ..and play again
+ //
+ Actor actor = Actor::New();
+ Stage::GetCurrent().Add(actor);
+
+ // Build the animation
+ float durationSeconds(1.0f);
+ Animation animation = Animation::New(durationSeconds);
+ Vector3 targetPosition(10.0f, 10.0f, 10.0f);
+ animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR);
+ animation.SetEndAction(Animation::Bake);
+
+ float intervalSeconds = 3.0f;
+
+ bool signalReceived(false);
+ AnimationFinishCheck finishCheck(signalReceived);
+ animation.FinishedSignal().Connect(&application, finishCheck);
+
+ animation.SetLoopCount(1);
+ animation.Play();
+ DALI_TEST_CHECK(!animation.IsLooping());
+
+ application.SendNotification();
+ finishCheck.CheckSignalNotReceived();
+ application.Render(static_cast<unsigned int>(durationSeconds*intervalSeconds*1000.0f));
+ application.SendNotification();
+ finishCheck.CheckSignalReceived();
+
+ DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION );
+ actor.SetProperty( Actor::Property::POSITION, Vector3(0.0f, 0.0f, 0.0f) );
+
+ finishCheck.Reset();
+
+ animation.Play(); // again
+ DALI_TEST_CHECK(!animation.IsLooping());
+
+ application.SendNotification();
+ finishCheck.CheckSignalNotReceived();
+ application.Render(static_cast<unsigned int>(durationSeconds*intervalSeconds*1000.0f));
+ application.SendNotification();
+ finishCheck.CheckSignalReceived();
+
+ DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION );
+
+ END_TEST;
+}
+
+int UtcDaliAnimationGetLoopCountP(void)
+{
+ TestApplication application;
+
+ Actor actor = Actor::New();
+ Stage::GetCurrent().Add(actor);
+
+ // Build the animation
+ float durationSeconds(1.0f);
+ Animation animation = Animation::New(durationSeconds);
+ Vector3 targetPosition(10.0f, 10.0f, 10.0f);
+ animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR);
+
+ DALI_TEST_CHECK(1 == animation.GetLoopCount());
+
+ // Start the animation
+ animation.SetLoopCount(3);
+ DALI_TEST_CHECK(animation.IsLooping());
+ DALI_TEST_CHECK(3 == animation.GetLoopCount());
+
+ animation.Play();
+
+ application.Render(0);
+ application.SendNotification();
+
+ // Loop
+ float intervalSeconds = 3.0f;
+
+ application.Render(static_cast<unsigned int>(durationSeconds*intervalSeconds*1000.0f));
+ application.Render(static_cast<unsigned int>(durationSeconds*intervalSeconds*1000.0f));
+
+ application.Render(0);
+ application.SendNotification();
+
+ application.Render(static_cast<unsigned int>(durationSeconds*intervalSeconds*1000.0f));
+ application.SendNotification();
+
+ animation.SetLoopCount(0);
+ DALI_TEST_CHECK(animation.IsLooping());
+ DALI_TEST_CHECK(0 == animation.GetLoopCount());
+
+ animation.SetLoopCount(1);
+ DALI_TEST_CHECK(!animation.IsLooping());
+ DALI_TEST_CHECK(1 == animation.GetLoopCount());
+
+ END_TEST;
+}
+
+
+int UtcDaliAnimationGetCurrentLoopP(void)
+{
+ TestApplication application;
+
+ Actor actor = Actor::New();
+ Stage::GetCurrent().Add(actor);
+
+ // Build the animation
+ float durationSeconds(1.0f);
+ Animation animation = Animation::New(durationSeconds);
+ Vector3 targetPosition(10.0f, 10.0f, 10.0f);
+ animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR);
+
+ // Start the animation
+ animation.SetLoopCount(3);
+ DALI_TEST_CHECK(animation.IsLooping());
+ DALI_TEST_CHECK(0 == animation.GetCurrentLoop());
+ animation.Play();
+
+ bool signalReceived(false);
+ AnimationFinishCheck finishCheck(signalReceived);
+ animation.FinishedSignal().Connect(&application, finishCheck);
+
+ application.SendNotification();
+
+ // Loop
+ float intervalSeconds = 3.0f;
+
+ application.Render(static_cast<unsigned int>(durationSeconds*intervalSeconds*1000.0f));
+ application.Render(static_cast<unsigned int>(durationSeconds*intervalSeconds*1000.0f));
+
+ application.SendNotification();
+ finishCheck.CheckSignalNotReceived();
+ DALI_TEST_CHECK(2 == animation.GetCurrentLoop());
+
+ application.Render(static_cast<unsigned int>(durationSeconds*intervalSeconds*1000.0f));
+
+ application.SendNotification();
+ finishCheck.CheckSignalReceived();
+ DALI_TEST_CHECK(3 == animation.GetCurrentLoop());
+ DALI_TEST_CHECK(animation.GetLoopCount() == animation.GetCurrentLoop());
+
+ finishCheck.Reset();
+
+ application.Render(static_cast<unsigned int>(durationSeconds*intervalSeconds*1000.0f));
+ application.SendNotification();
+ finishCheck.CheckSignalNotReceived();
+ DALI_TEST_CHECK(3 == animation.GetCurrentLoop());
+
+ application.Render(static_cast<unsigned int>(durationSeconds*intervalSeconds*1000.0f));
+ application.Render(static_cast<unsigned int>(durationSeconds*intervalSeconds*1000.0f));
+ application.Render(static_cast<unsigned int>(durationSeconds*intervalSeconds*1000.0f));
+ application.Render(static_cast<unsigned int>(durationSeconds*intervalSeconds*1000.0f));
+ application.SendNotification();
+ finishCheck.CheckSignalNotReceived();
+ DALI_TEST_CHECK(3 == animation.GetCurrentLoop());
+
+ END_TEST;
+}
+
int UtcDaliAnimationIsLoopingP(void)
{
TestApplication application;
DALI_TEST_CHECK( image );
- //ReleasePolicy is always never for framebuffer images
- DALI_TEST_EQUALS( image.GetReleasePolicy(), Image::NEVER, TEST_LOCATION );
+ // ReleasePolicy is deprecated. Only set, but not used internally.
+ DALI_TEST_EQUALS( image.GetReleasePolicy(), Image::UNUSED, TEST_LOCATION );
// initialise handle with NEVER release policy
image.Reset();
DALI_TEST_CHECK( image );
- //ReleasePolicy is always never for framebuffer images
+ // ReleasePolicy is deprecated. Only set, but not used internally.
DALI_TEST_EQUALS( image.GetReleasePolicy(), Image::NEVER, TEST_LOCATION );
END_TEST;
TestNativeImagePointer testNativeImage = TestNativeImage::New( 16, 16 );
DALI_TEST_CHECK( testNativeImage );
- DALI_TEST_CHECK( NULL == testNativeImage->GetExtension() );
+ DALI_TEST_CHECK( NULL != testNativeImage->GetExtension() );
END_TEST;
}
+
+int UtcDaliNativeImageGetCustomFragmentPreFixP(void)
+{
+ TestApplication application;
+ TestNativeImagePointer nativeImageInterface = TestNativeImage::New( 16, 16 );
+ NativeImage nativeImage = NativeImage::New( *(nativeImageInterface.Get()) );
+
+ const char* preFix = "#extension GL_OES_EGL_image_external:require\n";
+ DALI_TEST_EQUALS( nativeImage.GetCustomFragmentPreFix(), preFix, TEST_LOCATION );
+ END_TEST;
+}
+
+int UtcDaliNativeImageGetCustomSamplerTypenameP(void)
+{
+ TestApplication application;
+ TestNativeImagePointer nativeImageInterface = TestNativeImage::New( 16, 16 );
+ NativeImage nativeImage = NativeImage::New( *(nativeImageInterface.Get()) );
+
+ const char* samplerTypename = "samplerExternalOES";
+ DALI_TEST_EQUALS( nativeImage.GetCustomSamplerTypename(), samplerTypename, TEST_LOCATION );
+ END_TEST;
+}
#define BOOLSTR(x) ((x)?"T":"F")
+//& set: DaliRenderTask
using namespace Dali;
{
finishedSig = false;
callStack.Reset();
+
+ tet_printf("TestApplication::UpdateRender().\n");
+
application.Render(16);
application.SendNotification();
DALI_TEST_CHECK( finished );
finished = false;
- application.Render(); // Double check no more finished signal
- application.SendNotification();
- DALI_TEST_CHECK( ! finished );
+ DALI_TEST_EQUALS( application.GetUpdateStatus(), 0, TEST_LOCATION );
END_TEST;
}
application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
TestGlSyncAbstraction& sync = application.GetGlSyncAbstraction();
TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace();
+ sync.GetTrace().Enable(true);
drawTrace.Enable(true);
Actor rootActor = Actor::New();
Stage::GetCurrent().Add(secondRootActor);
- RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ALWAYS, true);
+ RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ALWAYS, /*GL-SYNC*/ true);
bool finished = false;
ConnectionTracker connectionTracker;
// START PROCESS/RENDER Input, Expected Input, Expected
DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, finished, false, false, __LINE__ ) );
Integration::GlSyncAbstraction::SyncObject* lastSyncObj = sync.GetLastSyncObject();
+ DALI_TEST_CHECK( lastSyncObj == NULL );
+ DALI_TEST_EQUALS( sync.GetTrace().CountMethod( "CreateSyncObject" ), 0, TEST_LOCATION );
+
// CHANGE TO RENDER ONCE,
newTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, finished, false, true, __LINE__ ) );
lastSyncObj = sync.GetLastSyncObject();
DALI_TEST_CHECK( lastSyncObj != NULL );
+ DALI_TEST_EQUALS( sync.GetNumberOfSyncObjects(), 1, TEST_LOCATION );
+ DALI_TEST_EQUALS( sync.GetTrace().CountMethod( "CreateSyncObject" ), 1, TEST_LOCATION );
DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true, __LINE__ ) );
+
+
+ DALI_TEST_EQUALS( sync.GetNumberOfSyncObjects(), 1, TEST_LOCATION );
+ DALI_TEST_EQUALS( sync.GetTrace().CountMethod( "CreateSyncObject" ), 1, TEST_LOCATION );
+
DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true, __LINE__ ) );
+ DALI_TEST_EQUALS( sync.GetNumberOfSyncObjects(), 1, TEST_LOCATION );
+ DALI_TEST_EQUALS( sync.GetTrace().CountMethod( "CreateSyncObject" ), 1, TEST_LOCATION );
+
sync.SetObjectSynced( lastSyncObj, true );
DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true, __LINE__ ) );
DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, true, false, __LINE__ ) );
DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true, __LINE__ ) );
DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true, __LINE__ ) );
+ TestGlSyncAbstraction& sync = application.GetGlSyncAbstraction();
+ Integration::GlSyncAbstraction::SyncObject* lastSyncObj = sync.GetLastSyncObject();
+ DALI_TEST_CHECK( lastSyncObj == NULL );
+
// FINISH RESOURCE LOADING
CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete
DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, finished, false, false, __LINE__ ) );
application.GetPlatform().ClearReadyResources();
+ lastSyncObj = sync.GetLastSyncObject();
+ DALI_TEST_CHECK( lastSyncObj == NULL );
+
newTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
application.SendNotification(); // Input, Expected Input, Expected
DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, finished, false, true, __LINE__ ) );
DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, true, false, __LINE__ ) );
+
+ lastSyncObj = sync.GetLastSyncObject();
+ DALI_TEST_CHECK( lastSyncObj == NULL );
+
END_TEST;
}
newTask.FinishedSignal().Connect( &application, renderTaskFinished );
application.SendNotification();
+ TestGlSyncAbstraction& sync = application.GetGlSyncAbstraction();
+ Integration::GlSyncAbstraction::SyncObject* lastSyncObj = sync.GetLastSyncObject();
+ DALI_TEST_CHECK( lastSyncObj == NULL );
+
// START PROCESS/RENDER Input, Expected Input, Expected
DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true, __LINE__ ) );
DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true, __LINE__ ) );
{
TestApplication application;
- tet_infoline("Testing RenderTask::SignalFinished()");
+ tet_infoline("Testing RenderTask::FinishInvisibleSourceActor()");
application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
TestGlSyncAbstraction& sync = application.GetGlSyncAbstraction();
Stage::GetCurrent().Add(actor);
- application.Render();
application.SendNotification();
application.Render();
application.SendNotification();
actor2.Add(actor);
actor.SetParentOrigin( Vector3(0,0,0) );
- application.Render();
application.SendNotification();
application.Render();
application.SendNotification();
// flush the queue and render once
application.SendNotification();
application.Render();
+ application.SendNotification();
+ application.Render();
float localX;
float localY;
devel_api_core_images_header_files = \
$(devel_api_src_dir)/images/atlas.h \
$(devel_api_src_dir)/images/distance-field.h \
- $(devel_api_src_dir)/images/pixel-data.h
+ $(devel_api_src_dir)/images/pixel-data.h \
+ $(devel_api_src_dir)/images/native-image-interface-extension.h
devel_api_core_object_header_files = \
$(devel_api_src_dir)/object/property-buffer.h \
--- /dev/null
+#ifndef __DALI_INTEGRATION_NATIVE_IMAGE_INTERFACE_EXTENSION_H__
+#define __DALI_INTEGRATION_NATIVE_IMAGE_INTERFACE_EXTENSION_H__
+
+/*
+ * Copyright (c) 2015 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 <dali/public-api/images/native-image-interface.h>
+
+namespace Dali
+{
+
+/**
+ * @brief Extension abstract interface to provide platform-specific support for handling image data.
+ *
+ */
+class NativeImageInterface::Extension
+{
+public:
+
+ class Extension2; ///< Forward declare future extension interface
+
+ /**
+ * @brief Get custom fragment prefix for rendering native image.
+ *
+ * @return Custom fragment prefix code as string.
+ */
+ virtual const char* GetCustomFragmentPreFix() = 0;
+
+ /**
+ * @brief Get custom sampler type name for rendering native image.
+ *
+ * @return Custom sampler type name.
+ */
+ virtual const char* GetCustomSamplerTypename() = 0;
+
+ /**
+ * @brief Retrieve the extension for the interface.
+ *
+ * @return Extension2 pointer if available, NULL otherwise
+ */
+ virtual Extension2* GetExtension2()
+ {
+ return NULL;
+ }
+
+protected:
+
+ /**
+ * @brief Destructor.
+ *
+ */
+ virtual ~Extension()
+ {
+ }
+
+};
+
+} // namespace Dali
+
+#endif // __DALI_INTEGRATION_NATIVE_IMAGE_INTERFACE_H__
#endif
+/* GL_OES_EGL_image_external */
+#ifndef GL_TEXTURE_EXTERNAL_OES
+#define GL_TEXTURE_EXTERNAL_OES 0x8D65
+#endif
+
+
#endif // __DALI_INTERNAL_GL_DEFINES_H__
mFinishedCallbackObject( NULL ),
mDurationSeconds( durationSeconds ),
mSpeedFactor(1.0f),
- mIsLooping( false ),
+ mLoopCount(1),
+ mCurrentLoop(0),
mPlayRange( Vector2(0.0f,1.0f)),
mEndAction( endAction ),
mDisconnectAction( disconnectAction ),
DALI_ASSERT_DEBUG( mAnimation == NULL );
// Create a new animation, temporarily owned
- SceneGraph::Animation* animation = SceneGraph::Animation::New( mDurationSeconds, mSpeedFactor, mPlayRange, mIsLooping, mEndAction, mDisconnectAction );
+ SceneGraph::Animation* animation = SceneGraph::Animation::New( mDurationSeconds, mSpeedFactor, mPlayRange, mLoopCount, mEndAction, mDisconnectAction );
// Keep a const pointer to the animation.
mAnimation = animation;
return mDurationSeconds;
}
-void Animation::SetLooping(bool looping)
+void Animation::SetLooping(bool on)
+{
+ SetLoopCount( on ? 0 : 1 );
+}
+
+void Animation::SetLoopCount(int count)
{
// Cache for public getters
- mIsLooping = looping;
+ mLoopCount = count;
// mAnimation is being used in a separate thread; queue a message to set the value
- SetLoopingMessage( mEventThreadServices, *mAnimation, looping );
+ SetLoopingMessage( mEventThreadServices, *mAnimation, mLoopCount );
+}
+
+int Animation::GetLoopCount()
+{
+ return mLoopCount;
+}
+
+int Animation::GetCurrentLoop()
+{
+ return mCurrentLoop;
}
bool Animation::IsLooping() const
{
- // This is not animatable; the cached value is up-to-date.
- return mIsLooping;
+ return mLoopCount != 1;
}
void Animation::SetEndAction(EndAction action)
bool Animation::HasFinished()
{
bool hasFinished(false);
- const int playCount(mAnimation->GetPlayCount());
+ const int playedCount(mAnimation->GetPlayedCount());
// If the play count has been incremented, then another notification is required
- if (playCount > mNotificationCount)
+ mCurrentLoop = mAnimation->GetCurrentLoop();
+
+ if (playedCount > mNotificationCount)
{
// Note that only one signal is emitted, if the animation has been played repeatedly
- mNotificationCount = playCount;
+ mNotificationCount = playedCount;
hasFinished = true;
}
/**
* @copydoc Dali::Animation::SetLooping()
*/
- void SetLooping(bool looping);
+ void SetLooping(bool on);
+
+ /**
+ * @copydoc Dali::Animation::SetLoopCount()
+ */
+ void SetLoopCount(int count);
+
+ /**
+ * @copydoc Dali::Animation::GetLoopCount()
+ */
+ int GetLoopCount();
+
+ /**
+ * @copydoc Dali::Animation::GetCurrentLoop()
+ */
+ int GetCurrentLoop();
/**
* @copydoc Dali::Animation::IsLooping()
// Cached for public getters
float mDurationSeconds;
float mSpeedFactor;
- bool mIsLooping;
+ int mLoopCount;
+ int mCurrentLoop;
Vector2 mPlayRange;
EndAction mEndAction;
EndAction mDisconnectAction;
// The animation may be present in mPlaylist - remove if necessary
// Note that the animation "Finish" signal is emitted after Stop() has been called
std::vector< Dali::Animation >::iterator iter = std::find( mPlaylist.begin(), mPlaylist.end(), Dali::Animation(animation) );
+ DALI_ASSERT_DEBUG(iter != mPlaylist.end());
mPlaylist.erase( iter );
}
}
{
return mIsNativeFbo;
}
+
+void FrameBufferImage::SetReleasePolicy( Dali::Image::ReleasePolicy releasePolicy )
+{
+ mReleasePolicy = releasePolicy;
+}
+
FrameBufferImage::~FrameBufferImage()
{
}
*/
bool IsNativeFbo() const;
+ /**
+ * @brief Required for backwards compatibility. Value is just stored but not used internally.
+ * @param[in] releasePolicy The release policy (ignored as not supported).
+ */
+ void SetReleasePolicy( Dali::Image::ReleasePolicy releasePolicy );
+
public: // From Image
/**
* @copydoc Dali::Internal::Image::Connect()
#include <dali/internal/event/common/thread-local-storage.h>
#include <dali/internal/event/resources/resource-client.h>
#include <dali/internal/event/common/stage-impl.h>
+#include <dali/devel-api/images/native-image-interface-extension.h>
using namespace Dali::Integration;
TypeRegistration mType( typeid(Dali::NativeImage), typeid(Dali::Image), NULL );
}
-NativeImage::NativeImage()
+NativeImage::NativeImage( NativeImageInterface& resourceData )
: Image()
{
+ NativeImageInterface::Extension* extension = resourceData.GetExtension();
+ if( extension != NULL )
+ {
+ mCustomFragmentPreFix = extension->GetCustomFragmentPreFix();
+ mCustomSamplerTypename = extension->GetCustomSamplerTypename();
+ }
}
NativeImagePtr NativeImage::New( NativeImageInterface& resourceData )
{
- NativeImagePtr image = new NativeImage;
+ NativeImagePtr image = new NativeImage( resourceData );
image->Initialize();
ResourceClient &resourceClient = ThreadLocalStorage::Get().GetResourceClient();
resourceClient.CreateGlTexture( GetResourceId() );
}
+const char* NativeImage::GetCustomFragmentPreFix()
+{
+ if( mCustomFragmentPreFix.empty() )
+ {
+ return NULL;
+ }
+
+ return mCustomFragmentPreFix.c_str();
+}
+
+const char* NativeImage::GetCustomSamplerTypename()
+{
+ if( mCustomSamplerTypename.empty() )
+ {
+ return NULL;
+ }
+
+ return mCustomSamplerTypename.c_str();
+}
+
} // namespace Internal
} // namespace Dali
*
*/
+// EXTERNAL INCLUDES
+#include <string>
+
// INTERNAL INCLUDES
#include <dali/public-api/images/native-image.h>
#include <dali/internal/event/images/image-impl.h>
/**
* Constructor
*/
- NativeImage();
+ NativeImage( NativeImageInterface& nativeImageInterface );
/**
* A reference counted object may only be deleted by calling Unreference()
*/
virtual ~NativeImage();
+
+public:
+
+ /**
+ * @copydoc Dali::NativeImageInterface::Extension::GetCustomFragmentPreFix()
+ */
+ const char* GetCustomFragmentPreFix();
+
+ /**
+ * @copydoc Dali::NativeImageInterface::Extension::GetCustomSamplerTypename()
+ */
+ const char* GetCustomSamplerTypename();
+
+private:
+ std::string mCustomFragmentPreFix;
+ std::string mCustomSamplerTypename;
};
} // namespace Internal
if( instruction.mRenderTracker && offscreen != NULL )
{
+ // This will create a sync object every frame this render tracker
+ // is alive (though it should be now be created only for
+ // render-once render tasks)
instruction.mRenderTracker->CreateSyncObject( mImpl->glSyncAbstraction );
instruction.mRenderTracker = NULL; // Only create once.
}
{
//Memory pool used to allocate new animations. Memory used by this pool will be released when shutting down DALi
Dali::Internal::MemoryPoolObjectAllocator<Dali::Internal::SceneGraph::Animation> gAnimationMemoryPool;
+
+inline void WrapInPlayRange( float& elapsed, const Dali::Vector2& playRangeSeconds)
+{
+ if (elapsed > playRangeSeconds.y )
+ {
+ elapsed = playRangeSeconds.x + fmod(elapsed, playRangeSeconds.y);
+ }
+ else if( elapsed < playRangeSeconds.x )
+ {
+ elapsed = playRangeSeconds.y - fmod(elapsed, playRangeSeconds.y);
+ }
+}
+
}
namespace Dali
namespace SceneGraph
{
-Animation* Animation::New( float durationSeconds, float speedFactor, const Vector2& playRange, bool isLooping, EndAction endAction, EndAction disconnectAction )
+Animation* Animation::New( float durationSeconds, float speedFactor, const Vector2& playRange, int loopCount, EndAction endAction, EndAction disconnectAction )
{
- return new ( gAnimationMemoryPool.AllocateRawThreadSafe() ) Animation( durationSeconds, speedFactor, playRange, isLooping, endAction, disconnectAction );
+ return new ( gAnimationMemoryPool.AllocateRawThreadSafe() ) Animation( durationSeconds, speedFactor, playRange, loopCount, endAction, disconnectAction );
}
-Animation::Animation( float durationSeconds, float speedFactor, const Vector2& playRange, bool isLooping, Dali::Animation::EndAction endAction, Dali::Animation::EndAction disconnectAction )
+Animation::Animation( float durationSeconds, float speedFactor, const Vector2& playRange, int loopCount, Dali::Animation::EndAction endAction, Dali::Animation::EndAction disconnectAction )
: mDurationSeconds(durationSeconds),
mSpeedFactor( speedFactor ),
- mLooping(isLooping),
mEndAction(endAction),
mDisconnectAction(disconnectAction),
mState(Stopped),
mElapsedSeconds(playRange.x*mDurationSeconds),
- mPlayCount(0),
+ mPlayedCount(0),
+ mLoopCount(loopCount),
+ mCurrentLoop(0),
mPlayRange( playRange )
{
}
mDurationSeconds = durationSeconds;
}
-void Animation::SetLooping(bool looping)
+void Animation::SetLoopCount(int loopCount)
{
- mLooping = looping;
+ mLoopCount = loopCount;
+ mCurrentLoop = 0;
}
void Animation::SetEndAction(Dali::Animation::EndAction action)
}
SetAnimatorsActive( true );
+
+ mCurrentLoop = 0;
}
void Animation::PlayFrom( float progress )
}
// The animation has now been played to completion
- ++mPlayCount;
+ ++mPlayedCount;
+ mCurrentLoop = 0;
}
mElapsedSeconds = mPlayRange.x*mDurationSeconds;
mAnimators.PushBack( animator );
}
-bool Animation::Update(BufferIndex bufferIndex, float elapsedSeconds)
+void Animation::Update(BufferIndex bufferIndex, float elapsedSeconds, bool& looped, bool& finished )
{
+ looped = false;
+ finished = false;
+
if (mState == Stopped || mState == Destroyed)
{
// Short circuit when animation isn't running
- return false;
+ return;
}
// The animation must still be applied when Paused/Stopping
}
Vector2 playRangeSeconds = mPlayRange * mDurationSeconds;
- if (mLooping)
+
+ if( 0 == mLoopCount )
{
- if (mElapsedSeconds > playRangeSeconds.y )
- {
- mElapsedSeconds = playRangeSeconds.x + fmod(mElapsedSeconds, playRangeSeconds.y);
- }
- else if( mElapsedSeconds < playRangeSeconds.x )
+ // loop forever
+ WrapInPlayRange(mElapsedSeconds, playRangeSeconds);
+
+ UpdateAnimators(bufferIndex, false, false);
+
+ // don't increment mPlayedCount as event loop tracks this to indicate animation finished (end of all loops)
+ }
+ else if( mCurrentLoop < mLoopCount - 1) // '-1' here so last loop iteration uses play once below
+ {
+ // looping
+ looped = (mState == Playing &&
+ (( mSpeedFactor > 0.0f && mElapsedSeconds > playRangeSeconds.y ) ||
+ ( mSpeedFactor < 0.0f && mElapsedSeconds < playRangeSeconds.x )) );
+
+ WrapInPlayRange(mElapsedSeconds, playRangeSeconds);
+
+ UpdateAnimators(bufferIndex, false, false);
+
+ if(looped)
{
- mElapsedSeconds = playRangeSeconds.y - fmod(mElapsedSeconds, playRangeSeconds.y);
+ ++mCurrentLoop;
+ // don't increment mPlayedCount until the finished final loop
}
}
+ else
+ {
+ // playing once (and last mCurrentLoop)
+ finished = (mState == Playing &&
+ (( mSpeedFactor > 0.0f && mElapsedSeconds > playRangeSeconds.y ) ||
+ ( mSpeedFactor < 0.0f && mElapsedSeconds < playRangeSeconds.x )) );
- const bool animationFinished(mState == Playing &&
- (( mSpeedFactor > 0.0f && mElapsedSeconds > playRangeSeconds.y ) ||
- ( mSpeedFactor < 0.0f && mElapsedSeconds < playRangeSeconds.x ))
- );
+ // update with bake if finished
+ UpdateAnimators(bufferIndex, finished && (mEndAction != Dali::Animation::Discard), finished);
- UpdateAnimators(bufferIndex, animationFinished && (mEndAction != Dali::Animation::Discard), animationFinished);
+ if(finished)
+ {
+ // The animation has now been played to completion
+ ++mPlayedCount;
- if (animationFinished)
- {
- // The animation has now been played to completion
- ++mPlayCount;
+ // loop iterations come to this else branch for their final iterations
+ if( mCurrentLoop < mLoopCount)
+ {
+ ++mCurrentLoop;
+ DALI_ASSERT_DEBUG(mCurrentLoop == mLoopCount);
+ }
- mElapsedSeconds = playRangeSeconds.x;
- mState = Stopped;
+ mElapsedSeconds = playRangeSeconds.x;
+ mState = Stopped;
+ }
}
- return animationFinished;
}
void Animation::UpdateAnimators( BufferIndex bufferIndex, bool bake, bool animationFinished )
* @param[in] durationSeconds The duration of the animation in seconds.
* @param[in] speedFactor Multiplier to the animation velocity.
* @param[in] playRange Minimum and maximum progress between which the animation will play.
- * @param[in] isLooping Whether the animation will loop.
+ * @param[in] loopCount The number of times the animation will loop. ( See SetLoopCount() )
* @param[in] endAction The action to perform when the animation ends.
* @param[in] disconnectAction The action to perform when the property owner of an animator is disconnected.
* @return A new Animation
*/
- static Animation* New( float durationSeconds, float speedFactor, const Vector2& playRange, bool isLooping, EndAction endAction, EndAction disconnectAction );
+ static Animation* New( float durationSeconds, float speedFactor, const Vector2& playRange, int loopCount, EndAction endAction, EndAction disconnectAction );
/**
* Virtual destructor
}
/**
- * Set whether the animation will loop.
- * @param[in] looping True if the animation will loop.
+ * Set the animation loop count.
+ * 0 is loop forever, N loop play N times
+ * @param[in] loopCount The loop count
*/
- void SetLooping(bool looping);
+ void SetLoopCount(int loopCount);
/**
* Query whether the animation will loop.
*/
bool IsLooping() const
{
- return mLooping;
+ return mLoopCount != 1;
+ }
+
+ /*
+ * Get the loop count
+ * @return the loop count
+ */
+ int GetLoopCount() const
+ {
+ return mLoopCount;
}
/**
* Retrive a count of the number of times the animation has been played to completion.
* This can be used to emit "Finised" signals from the public-api
*/
- int GetPlayCount() const
+ int GetPlayedCount() const
+ {
+ return mPlayedCount;
+ }
+
+ /**
+ * Get the current loop count from zero to GetLoopCount().
+ */
+ int GetCurrentLoop() const
{
- return mPlayCount;
+ return mCurrentLoop;
}
/**
* @pre The animation is playing or paused.
* @param[in] bufferIndex The buffer to update.
* @param[in] elapsedSeconds The time elapsed since the previous frame.
- * @return True if the animation has finished.
+ * @param[out] looped True if the animation looped
+ * @param[out] finished True if the animation has finished.
*/
- bool Update(BufferIndex bufferIndex, float elapsedSeconds);
+ void Update(BufferIndex bufferIndex, float elapsedSeconds, bool& looped, bool& finished );
protected:
/**
* Protected constructor. See New()
*/
- Animation( float durationSeconds, float speedFactor, const Vector2& playRange, bool isLooping, EndAction endAction, EndAction disconnectAction );
+ Animation( float durationSeconds, float speedFactor, const Vector2& playRange, int loopCount, EndAction endAction, EndAction disconnectAction );
private:
float mDurationSeconds;
float mSpeedFactor;
- bool mLooping;
EndAction mEndAction;
EndAction mDisconnectAction;
State mState;
float mElapsedSeconds;
- int mPlayCount;
+ int mPlayedCount; // Incremented at end of animation or completion of all loops
+ // Never incremented when looping forever. Event thread tracks to signal end.
+ int mLoopCount; // N loop setting
+ int mCurrentLoop; // Current loop number
Vector2 mPlayRange;
AnimatorContainer mAnimators;
new (slot) LocalType( &animation, &Animation::SetDuration, durationSeconds );
}
-inline void SetLoopingMessage( EventThreadServices& eventThreadServices, const Animation& animation, bool looping )
+inline void SetLoopingMessage( EventThreadServices& eventThreadServices, const Animation& animation, int loopCount )
{
- typedef MessageValue1< Animation, bool > LocalType;
+ typedef MessageValue1< Animation, int > LocalType;
// Reserve some memory inside the message queue
unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
// Construct message in the message queue memory; note that delete should not be called on the return value
- new (slot) LocalType( &animation, &Animation::SetLooping, looping );
+ new (slot) LocalType( &animation, &Animation::SetLoopCount, loopCount );
}
inline void SetEndActionMessage( EventThreadServices& eventThreadServices, const Animation& animation, Dali::Animation::EndAction action )
/**
* Rebuild the Layer::colorRenderables, stencilRenderables and overlayRenderables members,
* including only renderers which are included in the current render-task.
- * Returns true if all renderers have finshed acquiring resources.
+ * Returns true if all renderers have finished acquiring resources.
*/
bool AddRenderablesForTask( BufferIndex updateBufferIndex,
Node& node,
renderTask,
sourceNode->GetDrawMode() );
+ renderTask.SetResourcesFinished( resourcesFinished );
PrepareRenderInstruction( updateBufferIndex,
sortedLayers,
renderTask,
renderTask.GetCullMode(),
instructions );
}
-
- renderTask.SetResourcesFinished( resourcesFinished );
+ else
+ {
+ renderTask.SetResourcesFinished( resourcesFinished );
+ }
}
DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "ProcessRenderTasks() Onscreen\n");
{
AnimationContainer &animations = mImpl->animations;
AnimationIter iter = animations.Begin();
+ bool animationLooped = false;
while ( iter != animations.End() )
{
Animation* animation = *iter;
- bool finished = animation->Update( bufferIndex, elapsedSeconds );
+ bool finished = false;
+ bool looped = false;
+ animation->Update( bufferIndex, elapsedSeconds, looped, finished );
mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || finished;
+ animationLooped = animationLooped || looped;
// Remove animations that had been destroyed but were still waiting for an update
if (animation->GetState() == Animation::Destroyed)
}
}
- if ( mImpl->animationFinishedDuringUpdate )
+ // queue the notification on finished or looped (to update loop count)
+ if ( mImpl->animationFinishedDuringUpdate || animationLooped )
{
// The application should be notified by NotificationManager, in another thread
mImpl->notificationManager.QueueCompleteNotification( &mImpl->animationFinishedNotifier );
viewportSet ? &viewport : NULL,
mClearEnabled ? &GetClearColor( updateBufferIndex ) : NULL );
- // if using native framebuffer, add a tracker
- if( mTargetIsNativeFramebuffer )
+ if( mTargetIsNativeFramebuffer &&
+ mRefreshRate == Dali::RenderTask::REFRESH_ONCE &&
+ mResourcesFinished )
{
- // create tracker if not yet exists. if we switch to on-screen fbo, we still keep the tracker in case we need it again
+ // create tracker if one doesn't yet exist.
if( !mRenderSyncTracker )
{
mRenderSyncTracker = new Render::RenderTracker();
/**
* Prepares the render-instruction buffer to be populated with instructions.
+ *
+ * If the render task is a render-once framebuffer backed by a native image,
+ * then this method will ensure that a GL sync object is created to track
+ * when the rendering has finished.
+ *
* @param[out] instruction to prepare
* @param[in] updateBufferIndex The current update buffer index.
*/
public:
/**
+ * @DEPRECATED_1_1.11
* @brief An enumeration of properties belonging to the ImageActor class.
* Properties additional to RenderableActor.
* @SINCE_1_0.0
enum
{
/**
+ * @DEPRECATED_1_1.11
* @brief name "pixelArea", type Rect<int>
* @SINCE_1_0.0
*/
*/
BORDER,
/**
+ * @DEPRECATED_1_1.11
* @brief name "image", type Map {"filename":"", "loadPolicy":...}
* @SINCE_1_0.0
*/
*/
enum Style
{
- STYLE_QUAD, ///< As a simple quad. @SINCE_1_0.0
+ /**
+ * @DEPRECATED_1_1.11
+ * @brief As a simple quad.
+ * @SINCE_1_0.0
+ */
+ STYLE_QUAD,
/**
* @DEPRECATED_1_1.11
* @brief As a nine-patch.
};
/**
+ * @DEPRECATED_1_1.11
* @brief Pixel area is relative to the top-left (0,0) of the image.
* @SINCE_1_0.0
*/
static const BlendingMode::Type DEFAULT_BLENDING_MODE; ///< default value is BlendingMode::AUTO
/**
+ * @DEPRECATED_1_1.11
* @brief Create an uninitialized ImageActor handle.
*
* This can be initialized with ImageActor::New(...)
ImageActor();
/**
+ * @DEPRECATED_1_1.11
* @brief Create an empty image actor object.
*
* @SINCE_1_0.0
static ImageActor New();
/**
+ * @DEPRECATED_1_1.11
* @brief Create a image actor object.
*
* The actor will take the image's natural size unless a custom size
static ImageActor New(Image image);
/**
+ * @DEPRECATED_1_1.11
* @brief Create a image actor object.
*
* The actor will take the image's natural size unless a custom size
static ImageActor New(Image image, PixelArea pixelArea);
/**
+ * @DEPRECATED_1_1.11
* @brief Downcast an Object handle to ImageActor.
*
*
static ImageActor DownCast( BaseHandle handle );
/**
+ * @DEPRECATED_1_1.11
* @brief Destructor
*
* This is non-virtual since derived Handle types must not contain data or virtual methods.
~ImageActor();
/**
+ * @DEPRECATED_1_1.11
* @brief Copy constructor
*
* @SINCE_1_0.0
ImageActor(const ImageActor& copy);
/**
+ * @DEPRECATED_1_1.11
* @brief Assignment operator
*
* @SINCE_1_0.0
ImageActor& operator=(const ImageActor& rhs);
/**
+ * @DEPRECATED_1_1.11
* @brief Set the image rendered by the actor.
+ *
* Set the image rendered by the actor.
* If actor was already displaying a different image, the old image is dropped and actor may
* temporarily display nothing. Setting an empty image (handle) causes the current image to be
void SetImage(Image image);
/**
+ * @DEPRECATED_1_1.11
* @brief Retrieve the image rendered by the actor.
*
* If no image is assigned, an empty handle is returned
Image GetImage();
/**
+ * @DEPRECATED_1_1.11
* @brief Set a region of the image to display, in pixels.
*
* When the image is loaded the actor's size will be reset to the pixelArea,
void SetPixelArea(const PixelArea& pixelArea);
/**
+ * @DEPRECATED_1_1.11
* @brief Retrieve the region of the image to display, in pixels.
*
* @SINCE_1_0.0
/**
+ * @DEPRECATED_1_1.11
* @brief Allows modification of an actors position in the depth sort algorithm.
*
* The offset can be altered for each coplanar actor hence allowing an order of painting.
void SetSortModifier(float depthOffset);
/**
+ * @DEPRECATED_1_1.11
* @brief Retrieves the offset used to modify an actors position in the depth sort algorithm.
*
* The offset can be altered for each coplanar actor hence allowing an order of painting.
float GetSortModifier() const;
/**
+ * @DEPRECATED_1_1.11
* @brief Sets the blending mode.
*
* Possible values are: BlendingMode::OFF, BlendingMode::AUTO and BlendingMode::ON. Default is BlendingMode::AUTO.
void SetBlendMode( BlendingMode::Type mode );
/**
+ * @DEPRECATED_1_1.11
* @brief Retrieves the blending mode.
*
* @SINCE_1_0.0
BlendingMode::Type GetBlendMode() const;
/**
+ * @DEPRECATED_1_1.11
* @brief Specify the pixel arithmetic used when the actor is blended.
*
* @SINCE_1_0.0
void SetBlendFunc( BlendingFactor::Type srcFactorRgba, BlendingFactor::Type destFactorRgba );
/**
+ * @DEPRECATED_1_1.11
* @brief Specify the pixel arithmetic used when the actor is blended.
*
* @SINCE_1_0.0
BlendingFactor::Type srcFactorAlpha, BlendingFactor::Type destFactorAlpha );
/**
+ * @DEPRECATED_1_1.11
* @brief Query the pixel arithmetic used when the actor is blended.
*
* @SINCE_1_0.0
BlendingFactor::Type& srcFactorAlpha, BlendingFactor::Type& destFactorAlpha ) const;
/**
+ * @DEPRECATED_1_1.11
* @brief Specify the equation used when the actor is blended.
*
* The options are BlendingEquation::ADD, SUBTRACT, or REVERSE_SUBTRACT.
void SetBlendEquation( BlendingEquation::Type equationRgba );
/**
+ * @DEPRECATED_1_1.11
* @brief Specify the equation used when the actor is blended.
*
* @SINCE_1_0.0
void SetBlendEquation( BlendingEquation::Type equationRgb, BlendingEquation::Type equationAlpha );
/**
+ * @DEPRECATED_1_1.11
* @brief Query the equation used when the actor is blended.
*
* @SINCE_1_0.0
void GetBlendEquation( BlendingEquation::Type& equationRgb, BlendingEquation::Type& equationAlpha ) const;
/**
+ * @DEPRECATED_1_1.11
* @brief Specify the color used when the actor is blended; the default is Vector4::ZERO.
*
* @SINCE_1_0.0
void SetBlendColor( const Vector4& color );
/**
+ * @DEPRECATED_1_1.11
* @brief Query the color used when the actor is blended.
*
* @SINCE_1_0.0
const Vector4& GetBlendColor() const;
/**
+ * @DEPRECATED_1_1.11
* @brief Sets the filtering mode.
*
* Possible values are: FilterMode::NEAREST and FilterMode::LINEAR. Default is FilterMode::LINEAR.
void SetFilterMode( FilterMode::Type minFilter, FilterMode::Type magFilter );
/**
+ * @DEPRECATED_1_1.11
* @brief Retrieves the filtering mode.
*
* @SINCE_1_0.0
void GetFilterMode( FilterMode::Type& minFilter, FilterMode::Type& magFilter) const;
/**
+ * @DEPRECATED_1_1.11
* @brief Sets the shader effect for the RenderableActor.
*
* Shader effects provide special effects like ripple and bend.
void SetShaderEffect( ShaderEffect effect );
/**
+ * @DEPRECATED_1_1.11
* @brief Retrieve the custom shader effect for the RenderableActor.
* If default shader is used an empty handle is returned.
*
ShaderEffect GetShaderEffect() const;
/**
+ * @DEPRECATED_1_1.11
* @brief Removes the current shader effect.
*
* @SINCE_1_0.0
/**
+ * @DEPRECATED_1_1.11
* @brief Sets the shader effect for all ImageActors in a tree of Actors.
*
* @SINCE_1_0.0
DALI_IMPORT_API void SetShaderEffectRecursively( Actor actor, ShaderEffect effect );
/**
+ * @DEPRECATED_1_1.11
* @brief Removes the shader effect from all ImageActors in a tree of Actors.
*
* @SINCE_1_0.0
LAYER_2D,
/**
- * @brief Layer will use depth test and do several clears.
+ * @brief Layer will use depth test.
+ *
+ * When using this mode depth depth test will be used. Opaque renderers are drawn first
+ * and write to the depth buffer. Then transparent renderers are drawn with depth test
+ * enabled but depth write switched off.
+ * Transparent renderers are drawn based on their distance from the camera (painter's algorithm).
+ * A renderers DEPTH_INDEX property is used to offset the distance to the camera when ordering transparent renderers.
+ * This is useful if you want to define the draw order of two or more transparent renderers that are
+ * equal distance from the camera.
*
- * When using this mode depth depth test will be used. A depth clear will happen for each distinct
- * depth-index value in the layer, opaque renderers are drawn first and write to the depth buffer.
- * Then transparent renderers are drawn with depth test enabled but depth write switched off.
* @SINCE_1_0.0
*/
LAYER_3D,
GetImplementation(*this).SetLooping(looping);
}
+void Animation::SetLoopCount(int count)
+{
+ GetImplementation(*this).SetLoopCount(count);
+}
+
+int Animation::GetLoopCount()
+{
+ return GetImplementation(*this).GetLoopCount();
+}
+
+int Animation::GetCurrentLoop()
+{
+ return GetImplementation(*this).GetCurrentLoop();
+}
+
bool Animation::IsLooping() const
{
return GetImplementation(*this).IsLooping();
float GetDuration() const;
/**
- * @brief Set whether the animation will loop.
+ * @brief Set whether the animation will loop forever.
+ *
+ * This function resets the loop count and should not be used with SetLoopCount(int).
+ * Setting this parameter does not cause the animation to Play()
*
* @SINCE_1_0.0
- * @param[in] looping True if the animation will loop.
+ * @param[in] looping If true then the animation will loop forever, if false it will never loop.
*/
void SetLooping(bool looping);
/**
+ * @brief Enable looping for 'count' repeats.
+ *
+ * A zero is the same as SetLooping(true) ie repeat forever.
+ * If Play() Stop() or 'count' loops is reached, the loop counter will reset.
+ * Setting this parameter does not cause the animation to Play()
+ *
+ * @SINCE_1_1.20
+ * @param[in] count The number of times to loop.
+ */
+ void SetLoopCount(int count);
+
+ /**
+ * @brief Get the loop count.
+ *
+ * A zero is the same as SetLooping(true) ie repeat forever.
+ * The loop count is initially 1 for play once.
+ *
+ * @SINCE_1_1.20
+ * @return The number of times to loop.
+ */
+ int GetLoopCount();
+
+ /**
+ * @brief Get the current loop count.
+ *
+ * A value 0 to GetLoopCount() indicating the current loop count when looping.
+ *
+ * @SINCE_1_1.20
+ * @return The current number of loops that have occured.
+ */
+ int GetCurrentLoop();
+
+ /**
* @brief Query whether the animation will loop.
*
* @SINCE_1_0.0
const unsigned int CORE_MAJOR_VERSION = 1;
const unsigned int CORE_MINOR_VERSION = 1;
-const unsigned int CORE_MICRO_VERSION = 19;
+const unsigned int CORE_MICRO_VERSION = 20;
const char * const CORE_BUILD_DATE = __DATE__ " " __TIME__;
#ifndef EMSCRIPTEN
return FrameBufferImage(internal.Get());
}
-FrameBufferImage FrameBufferImage::New( unsigned int width, unsigned int height, Pixel::Format pixelformat, ReleasePolicy /*releasePolicy*/, RenderBuffer::Format bufferformat )
+FrameBufferImage FrameBufferImage::New( unsigned int width, unsigned int height, Pixel::Format pixelformat, ReleasePolicy releasePolicy, RenderBuffer::Format bufferformat )
{
Dali::Vector2 stageSize = Stage::GetCurrent().GetSize();
Internal::FrameBufferImagePtr internal = Internal::FrameBufferImage::New(
pixelformat,
bufferformat);
+ internal->SetReleasePolicy( releasePolicy );
return FrameBufferImage(internal.Get());
}
-FrameBufferImage FrameBufferImage::New( NativeImageInterface& image, ReleasePolicy /*releasePolicy*/ )
+FrameBufferImage FrameBufferImage::New( NativeImageInterface& image, ReleasePolicy releasePolicy )
{
Internal::FrameBufferImagePtr internal = Internal::FrameBufferImage::New( image );
+ internal->SetReleasePolicy( releasePolicy );
return FrameBufferImage(internal.Get());
}
return NativeImage( dynamic_cast<Internal::NativeImage*>( handle.GetObjectPtr()) );
}
+const char* NativeImage::GetCustomSamplerTypename()
+{
+ return GetImplementation(*this).GetCustomSamplerTypename();
+}
+
+const char* NativeImage::GetCustomFragmentPreFix()
+{
+ return GetImplementation(*this).GetCustomFragmentPreFix();
+}
+
} // namespace Dali
* If not, the returned handle is left unintialized.
* @SINCE_1_0.0
* @param[in] handle Handle to an object.
- * @return handle to a NativeImage or an uninitialized handle.
+ * @return Handle to a NativeImage or an uninitialized handle.
*/
static NativeImage DownCast( BaseHandle handle );
+ /**
+ * @brief Get custom fragment prefix for rendering a native image.
+ *
+ * @return String for custom fragment prefix
+ */
+ const char* GetCustomFragmentPreFix();
+
+ /**
+ * @brief Get custom sampler type name for rendering a native image.
+ *
+ * @return String for custom sampler type name
+ */
+ const char* GetCustomSamplerTypename();
+
public: // Not intended for application developers
explicit DALI_INTERNAL NativeImage( Internal::NativeImage* );
*/
/**
+ * @DEPRECATED_1_0.47
* @brief DALI_COMPOSE_SHADER macro provides a convenient way to write shader source code.
*
* We normally use double quotation marks to write a string such as "Hello World".
// Default Properties
/**
+ * @DEPRECATED_1_0.47
* @brief An enumeration of properties belonging to the ShaderEffect class.
* Grid Density defines the spacing of vertex coordinates in world units.
* ie a larger actor will have more grids at the same spacing.
{
enum
{
- GRID_DENSITY = DEFAULT_ACTOR_PROPERTY_START_INDEX, ///< name "gridDensity", type float @SINCE_1_0.0
- IMAGE, ///< name "image", type Map {"filename":"", "loadPolicy":...} @SINCE_1_0.0
- PROGRAM, ///< name "program", type Map {"vertexPrefix":"","fragmentPrefix":"","vertex":"","fragment":""} @SINCE_1_0.0
- GEOMETRY_HINTS ///< name "geometryHints", type int (bitfield) values from enum GeometryHints @SINCE_1_0.0
+ GRID_DENSITY = DEFAULT_ACTOR_PROPERTY_START_INDEX, ///< @DEPRECATED_1_0.47 @brief name "gridDensity", type float @SINCE_1_0.0
+ IMAGE, ///< @DEPRECATED_1_0.47 @brief name "image", type Map {"filename":"", "loadPolicy":...} @SINCE_1_0.0
+ PROGRAM, ///< @DEPRECATED_1_0.47 @brief name "program", type Map {"vertexPrefix":"","fragmentPrefix":"","vertex":"","fragment":""} @SINCE_1_0.0
+ GEOMETRY_HINTS ///< @DEPRECATED_1_0.47 @brief name "geometryHints", type int (bitfield) values from enum GeometryHints @SINCE_1_0.0
};
};
static const float DEFAULT_GRID_DENSITY; ///< The default density is 40 pixels
/**
+ * @DEPRECATED_1_0.47
* @brief Hints for rendering/subdividing geometry.
* @SINCE_1_0.0
*/
enum GeometryHints
{
- HINT_NONE = 0x00, ///< no hints @SINCE_1_0.0
- HINT_GRID_X = 0x01, ///< Geometry must be subdivided in X @SINCE_1_0.0
- HINT_GRID_Y = 0x02, ///< Geometry must be subdivided in Y @SINCE_1_0.0
- HINT_GRID = (HINT_GRID_X | HINT_GRID_Y),
- HINT_DEPTH_BUFFER = 0x04, ///< Needs depth buffering turned on @SINCE_1_0.0
- HINT_BLENDING = 0x08, ///< Notifies the actor to use blending even if it's fully opaque. Needs actor's blending set to BlendingMode::AUTO @SINCE_1_0.0
- HINT_DOESNT_MODIFY_GEOMETRY = 0x10 ///< Notifies that the vertex shader will not change geometry (enables bounding box culling) @SINCE_1_0.0
+ HINT_NONE = 0x00, ///< @DEPRECATED_1_0.47 @brief no hints @SINCE_1_0.0
+ HINT_GRID_X = 0x01, ///< @DEPRECATED_1_0.47 @brief Geometry must be subdivided in X @SINCE_1_0.0
+ HINT_GRID_Y = 0x02, ///< @DEPRECATED_1_0.47 @brief Geometry must be subdivided in Y @SINCE_1_0.0
+ HINT_GRID = (HINT_GRID_X | HINT_GRID_Y), ///< @DEPRECATED_1_0.47 @brief HINT_GRID_X | HINT_GRID_Y @SINCE_1_0.0
+ HINT_DEPTH_BUFFER = 0x04, ///< @DEPRECATED_1_0.47 @brief Needs depth buffering turned on @SINCE_1_0.0
+ HINT_BLENDING = 0x08, ///< @DEPRECATED_1_0.47 @brief Notifies the actor to use blending even if it's fully opaque. Needs actor's blending set to BlendingMode::AUTO @SINCE_1_0.0
+ HINT_DOESNT_MODIFY_GEOMETRY = 0x10 ///< @DEPRECATED_1_0.47 @brief Notifies that the vertex shader will not change geometry (enables bounding box culling) @SINCE_1_0.0
};
/**
+ * @DEPRECATED_1_0.47
* @brief Coordinate type of the shader uniform.
*
* Viewport coordinate types will convert from viewport to view space.
*/
enum UniformCoordinateType
{
- COORDINATE_TYPE_DEFAULT, ///< @brief Default, No transformation to be applied @SINCE_1_0.0
- COORDINATE_TYPE_VIEWPORT_POSITION, ///< @DEPRECATED_1_1.11 @brief The uniform is a position vector in viewport coordinates that needs to be converted to GL view space coordinates. @SINCE_1_0.0
- COORDINATE_TYPE_VIEWPORT_DIRECTION ///< @DEPRECATED_1_1.11 @brief The uniform is a directional vector in viewport coordinates that needs to be converted to GL view space coordinates. @SINCE_1_0.0
+ COORDINATE_TYPE_DEFAULT, ///< @DEPRECATED_1_0.47 @brief Default, No transformation to be applied @SINCE_1_0.0
+ COORDINATE_TYPE_VIEWPORT_POSITION, ///< @DEPRECATED_1_0.47 @brief The uniform is a position vector in viewport coordinates that needs to be converted to GL view space coordinates. @SINCE_1_0.0
+ COORDINATE_TYPE_VIEWPORT_DIRECTION ///< @DEPRECATED_1_0.47 @brief The uniform is a directional vector in viewport coordinates that needs to be converted to GL view space coordinates. @SINCE_1_0.0
};
/**
+ * @DEPRECATED_1_0.47
* @brief Create an empty ShaderEffect.
*
* This can be initialised with ShaderEffect::New(...)
ShaderEffect();
/**
+ * @DEPRECATED_1_0.47
* @brief Create ShaderEffect.
*
* @SINCE_1_0.0
GeometryHints hints = GeometryHints(HINT_NONE) );
/**
+ * @DEPRECATED_1_0.47
* @brief Create ShaderEffect.
* @SINCE_1_0.0
* @param vertexShaderPrefix code for the effect. It will be inserted before the default uniforms (ideal for \#defines)
GeometryHints hints = GeometryHints(HINT_NONE) );
/**
+ * @DEPRECATED_1_0.47
* @brief Downcast an Object handle to ShaderEffect.
*
* If handle points to a ShaderEffect the downcast produces valid
static ShaderEffect DownCast( BaseHandle handle );
/**
+ * @DEPRECATED_1_0.47
* @brief Destructor
*
* This is non-virtual since derived Handle types must not contain data or virtual methods.
~ShaderEffect();
/**
+ * @DEPRECATED_1_0.47
* @brief Copy constructor
*
* @SINCE_1_0.0
ShaderEffect(const ShaderEffect& object);
/**
+ * @DEPRECATED_1_0.47
* @brief This assignment operator is required for (smart) pointer semantics.
*
* @SINCE_1_0.0
ShaderEffect& operator=(const ShaderEffect& rhs);
/**
+ * @DEPRECATED_1_0.47
* @brief Sets image for using as effect texture.
*
* This image texture will be bound to the "sEffect" sampler
void SetEffectImage( Image image );
/**
+ * @DEPRECATED_1_0.47
* @brief Set a uniform value.
+ *
* This will register a property of type Property::FLOAT; see Object::RegisterProperty() for more details.
* If name matches a uniform in the shader source, this value will be uploaded when rendering.
* @SINCE_1_0.0
UniformCoordinateType uniformCoordinateType = UniformCoordinateType(COORDINATE_TYPE_DEFAULT) );
/**
+ * @DEPRECATED_1_0.47
* @brief Set a uniform value.
*
* This will register a property of type Property::VECTOR2; see Object::RegisterProperty() for more details.
UniformCoordinateType uniformCoordinateType = UniformCoordinateType(COORDINATE_TYPE_DEFAULT) );
/**
+ * @DEPRECATED_1_0.47
* @brief Set a uniform value.
*
* This will register a property of type Property::VECTOR3; see Object::RegisterProperty() for more details.
UniformCoordinateType uniformCoordinateType = UniformCoordinateType(COORDINATE_TYPE_DEFAULT) );
/**
+ * @DEPRECATED_1_0.47
* @brief Set a uniform value.
*
* This will register a property of type Property::VECTOR4; see Object::RegisterProperty() for more details.
UniformCoordinateType uniformCoordinateType = UniformCoordinateType(COORDINATE_TYPE_DEFAULT) );
/**
+ * @DEPRECATED_1_0.47
* @brief Set a uniform value.
*
* This will register a property of type Property::MATRIX; see Object::RegisterProperty() for more details.
UniformCoordinateType uniformCoordinateType = UniformCoordinateType(COORDINATE_TYPE_DEFAULT) );
/**
+ * @DEPRECATED_1_0.47
* @brief Set a uniform value.
*
* This will register a property of type Property::MATRIX3; see Object::RegisterProperty() for more details.
public: // Not intended for application developers
/**
+ * @DEPRECATED_1_0.47
* @brief This constructor is used by Dali New() methods.
* @SINCE_1_0.0
* @param [in] effect A pointer to a newly allocated Dali resource.
Name: dali
Summary: The OpenGLES Canvas Core Library
-Version: 1.1.19
+Version: 1.1.20
Release: 1
Group: System/Libraries
License: Apache-2.0 and BSD-2-Clause and MIT