dali-toolkit-test-utils/toolkit-physical-keyboard.cpp
dali-toolkit-test-utils/toolkit-style-monitor.cpp
dali-toolkit-test-utils/toolkit-test-application.cpp
+ dali-toolkit-test-utils/toolkit-texture-upload-manager.cpp
dali-toolkit-test-utils/toolkit-timer.cpp
dali-toolkit-test-utils/toolkit-trigger-event-factory.cpp
dali-toolkit-test-utils/toolkit-tts-player.cpp
return graphicsProgram->GetParameter(parameterId, outData);
}
+Graphics::Texture* TestGraphicsController::CreateTextureByResourceId(uint32_t resourceId, const Graphics::TextureCreateInfo& createInfo)
+{
+ Graphics::Texture* ret = nullptr;
+ Graphics::UniquePtr<Graphics::Texture> texture;
+ TraceCallStack::NamedParams namedParams;
+ namedParams["resourceId"] << resourceId;
+
+ auto iter = mTextureUploadBindMapper.find(resourceId);
+ DALI_ASSERT_ALWAYS(iter == mTextureUploadBindMapper.end());
+
+ // Create new graphics texture.
+ texture = CreateTexture(createInfo, std::move(texture));
+ ret = texture.get();
+
+ mTextureUploadBindMapper.insert(std::make_pair(resourceId, std::move(texture)));
+
+ mCallStack.PushCall("CreateTextureByResourceId", "", namedParams);
+ return ret;
+}
+
+void TestGraphicsController::DiscardTextureFromResourceId(uint32_t resourceId)
+{
+ TraceCallStack::NamedParams namedParams;
+ namedParams["resourceId"] << resourceId;
+
+ mTextureUploadBindMapper.erase(resourceId);
+
+ mCallStack.PushCall("DiscardTextureFromResourceId", "", namedParams);
+}
+
+Graphics::Texture* TestGraphicsController::GetTextureFromResourceId(uint32_t resourceId)
+{
+ TraceCallStack::NamedParams namedParams;
+ namedParams["resourceId"] << resourceId;
+
+ Graphics::Texture* ret = nullptr;
+
+ auto iter = mTextureUploadBindMapper.find(resourceId);
+ if(iter != mTextureUploadBindMapper.end())
+ {
+ ret = iter->second.get();
+ }
+
+ mCallStack.PushCall("GetTextureFromResourceId", "", namedParams);
+
+ return ret;
+}
+
+Graphics::UniquePtr<Graphics::Texture> TestGraphicsController::ReleaseTextureFromResourceId(uint32_t resourceId)
+{
+ TraceCallStack::NamedParams namedParams;
+ namedParams["resourceId"] << resourceId;
+
+ Graphics::UniquePtr<Graphics::Texture> texture;
+
+ auto iter = mTextureUploadBindMapper.find(resourceId);
+ if(iter != mTextureUploadBindMapper.end())
+ {
+ texture = std::move(iter->second);
+ mTextureUploadBindMapper.erase(iter);
+ }
+
+ mCallStack.PushCall("ReleaseTextureFromResourceId", "", namedParams);
+
+ return texture;
+}
+
} // namespace Dali
*/
#include <dali/graphics-api/graphics-controller.h>
+#include <unordered_map>
#include "test-gl-abstraction.h"
#include "test-gl-context-helper-abstraction.h"
#include "test-graphics-command-buffer.h"
*/
bool PipelineEquals(const Graphics::Pipeline& pipeline0, const Graphics::Pipeline& pipeline1) const override;
+ /**
+ * @brief Retrieves program parameters
+ *
+ * This function can be used to retrieve data from internal implementation
+ *
+ * @param[in] program Valid program object
+ * @param[in] parameterId Integer parameter id
+ * @param[out] outData Pointer to output memory
+ * @return True on success
+ */
+ bool GetProgramParameter(Graphics::Program& program, uint32_t parameterId, void* outData) override;
+
+public: // ResourceId relative API.
+ /**
+ * @brief Create Graphics::Texture as resourceId.
+ * The ownership of Graphics::Texture will be hold on this controller.
+ * @note If some Graphics::Texture already created before, assert.
+ * @post DiscardTextureFromResourceId() or ReleaseTextureFromResourceId() should be called when we don't use resourceId texture anymore.
+ *
+ * @param[in] resourceId The unique id of resouces.
+ * @return Pointer of Graphics::Texture, or nullptr if we fail to create.
+ */
+ Graphics::Texture* CreateTextureByResourceId(uint32_t resourceId, const Graphics::TextureCreateInfo& createInfo) override;
+
+ /**
+ * @brief Discard Graphics::Texture as resourceId.
+ *
+ * @param[in] resourceId The unique id of resouces.
+ */
+ void DiscardTextureFromResourceId(uint32_t resourceId) override;
+
+ /**
+ * @brief Get the Graphics::Texture as resourceId.
+ *
+ * @param[in] resourceId The unique id of resouces.
+ * @return Pointer of Graphics::Texture, or nullptr if there is no valid objects.
+ */
+ Graphics::Texture* GetTextureFromResourceId(uint32_t resourceId) override;
+
+ /**
+ * @brief Get the ownership of Graphics::Texture as resourceId.
+ *
+ * @param[in] resourceId The unique id of resouces.
+ * @return Pointer of Graphics::Texture.
+ */
+ Graphics::UniquePtr<Graphics::Texture> ReleaseTextureFromResourceId(uint32_t resourceId) override;
+
public: // Test Functions
void SetVertexFormats(Property::Array& vfs)
{
mSubmitStack.clear();
}
- /**
- * @brief Retrieves program parameters
- *
- * This function can be used to retrieve data from internal implementation
- *
- * @param[in] program Valid program object
- * @param[in] parameterId Integer parameter id
- * @param[out] outData Pointer to output memory
- * @return True on success
- */
- bool GetProgramParameter(Graphics::Program& program, uint32_t parameterId, void* outData) override;
-
void ProcessCommandBuffer(TestGraphicsCommandBuffer& commandBuffer);
void BindPipeline(TestGraphicsPipeline* pipeline);
std::vector<TestGraphicsBuffer*> mAllocatedBuffers;
+ std::unordered_map<uint32_t, Graphics::UniquePtr<Graphics::Texture>> mTextureUploadBindMapper;
+
struct PipelineCache
{
};
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * 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.
#include <dali/integration-api/adaptor-framework/adaptor.h>
#include <dali/integration-api/adaptor-framework/scene-holder.h>
-#include <toolkit-scene-holder-impl.h>
-#include <toolkit-adaptor-impl.h>
#include <dali/integration-api/debug.h>
#include <dali/integration-api/scene.h>
#include <test-application.h>
+#include <toolkit-adaptor-impl.h>
+#include <toolkit-scene-holder-impl.h>
#include <toolkit-test-application.h>
namespace Dali
{
-
namespace Internal
{
namespace Adaptor
{
-
///////////////////////////////////////////////////////////////////////////////
//
// Dali::Internal::Adaptor::Adaptor Stub
Dali::Adaptor& Adaptor::New()
{
- DALI_ASSERT_ALWAYS( ! gAdaptor );
+ DALI_ASSERT_ALWAYS(!gAdaptor);
gAdaptor = new Dali::Adaptor;
return *gAdaptor;
}
Dali::Adaptor& Adaptor::Get()
{
- DALI_ASSERT_ALWAYS( gAdaptor );
+ DALI_ASSERT_ALWAYS(gAdaptor);
return *gAdaptor;
}
gAdaptor = nullptr;
}
-void Adaptor::Start( Dali::Window window )
+void Adaptor::Start(Dali::Window window)
{
- AddWindow( &GetImplementation( window ) );
+ AddWindow(&GetImplementation(window));
}
-Integration::Scene Adaptor::GetScene( Dali::Window window )
+Integration::Scene Adaptor::GetScene(Dali::Window window)
{
return window.GetScene();
}
-bool Adaptor::AddIdle( CallbackBase* callback, bool hasReturnValue )
+bool Adaptor::AddIdle(CallbackBase* callback, bool hasReturnValue)
{
- mCallbacks.PushBack( callback );
+ mCallbacks.PushBack(callback);
return true;
}
-void Adaptor::RemoveIdle( CallbackBase* callback )
+void Adaptor::RemoveIdle(CallbackBase* callback)
{
- mCallbacks.Erase( std::find_if( mCallbacks.Begin(), mCallbacks.End(),
- [ &callback ] ( CallbackBase* current ) { return callback == current; } ) );
+ mCallbacks.Erase(std::find_if(mCallbacks.Begin(), mCallbacks.End(), [&callback](CallbackBase* current) { return callback == current; }));
}
void Adaptor::RunIdles()
{
- for( auto& callback : mCallbacks )
+ for(auto& callback : mCallbacks)
{
- CallbackBase::Execute( *callback );
+ CallbackBase::Execute(*callback);
}
mCallbacks.Clear();
Dali::RenderSurfaceInterface& Adaptor::GetSurface()
{
- DALI_ASSERT_ALWAYS( ! mWindows.empty() );
+ DALI_ASSERT_ALWAYS(!mWindows.empty());
- return reinterpret_cast < Dali::RenderSurfaceInterface& >( mWindows.front()->GetRenderSurface() );
+ return reinterpret_cast<Dali::RenderSurfaceInterface&>(mWindows.front()->GetRenderSurface());
}
Dali::WindowContainer Adaptor::GetWindows()
{
Dali::WindowContainer windows;
- for ( auto iter = mWindows.begin(); iter != mWindows.end(); ++iter )
+ for(auto iter = mWindows.begin(); iter != mWindows.end(); ++iter)
{
// Downcast to Dali::Window
- Dali::Window window( dynamic_cast<Dali::Internal::Adaptor::Window*>( *iter ) );
- if ( window )
+ Dali::Window window(dynamic_cast<Dali::Internal::Adaptor::Window*>(*iter));
+ if(window)
{
- windows.push_back( window );
+ windows.push_back(window);
}
}
{
Dali::SceneHolderList sceneHolderList;
- for( auto iter = mWindows.begin(); iter != mWindows.end(); ++iter )
+ for(auto iter = mWindows.begin(); iter != mWindows.end(); ++iter)
{
- sceneHolderList.push_back( Dali::Integration::SceneHolder( *iter ) );
+ sceneHolderList.push_back(Dali::Integration::SceneHolder(*iter));
}
return sceneHolderList;
}
-Dali::Internal::Adaptor::SceneHolder* Adaptor::GetWindow( Dali::Actor& actor )
+Dali::Internal::Adaptor::SceneHolder* Adaptor::GetWindow(Dali::Actor& actor)
{
- Dali::Integration::Scene scene = Dali::Integration::Scene::Get( actor );
+ Dali::Integration::Scene scene = Dali::Integration::Scene::Get(actor);
- for( auto window : mWindows )
+ for(auto window : mWindows)
{
- if ( scene == window->GetScene() )
+ if(scene == window->GetScene())
{
return window;
}
return nullptr;
}
-void Adaptor::AddWindow( Internal::Adaptor::SceneHolder* window )
+void Adaptor::AddWindow(Internal::Adaptor::SceneHolder* window)
{
- if ( window )
+ if(window)
{
- mWindows.push_back( window );
+ mWindows.push_back(window);
- Dali::Integration::SceneHolder newWindow( window );
- mWindowCreatedSignal.Emit( newWindow );
+ Dali::Integration::SceneHolder newWindow(window);
+ mWindowCreatedSignal.Emit(newWindow);
}
}
-void Adaptor::RemoveWindow( Internal::Adaptor::SceneHolder* window )
+void Adaptor::RemoveWindow(Internal::Adaptor::SceneHolder* window)
{
- auto iter = std::find( mWindows.begin(), mWindows.end(), window );
- if( iter != mWindows.end() )
+ auto iter = std::find(mWindows.begin(), mWindows.end(), window);
+ if(iter != mWindows.end())
{
- mWindows.erase( iter );
+ mWindows.erase(iter);
}
}
-void Adaptor::RegisterProcessor( Integration::Processor& processor, bool postProcessor )
+void Adaptor::RegisterProcessor(Integration::Processor& processor, bool postProcessor)
{
Integration::Core& core = mTestApplication->GetCore();
- core.RegisterProcessor( processor, postProcessor );
+ core.RegisterProcessor(processor, postProcessor);
}
-void Adaptor::UnregisterProcessor( Integration::Processor& processor, bool postProcessor )
+void Adaptor::UnregisterProcessor(Integration::Processor& processor, bool postProcessor)
{
Integration::Core& core = mTestApplication->GetCore();
- core.UnregisterProcessor( processor, postProcessor );
+ core.UnregisterProcessor(processor, postProcessor);
}
-void Adaptor::SetApplication( Dali::TestApplication& testApplication )
+void Adaptor::SetApplication(Dali::TestApplication& testApplication)
{
mTestApplication = &testApplication;
}
///////////////////////////////////////////////////////////////////////////////
Adaptor::Adaptor()
-: mImpl( new Internal::Adaptor::Adaptor )
+: mImpl(new Internal::Adaptor::Adaptor)
{
}
{
}
-bool Adaptor::AddIdle( CallbackBase* callback, bool hasReturnValue )
+bool Adaptor::AddIdle(CallbackBase* callback, bool hasReturnValue)
{
- return mImpl->AddIdle( callback, hasReturnValue );
+ return mImpl->AddIdle(callback, hasReturnValue);
}
-void Adaptor::RemoveIdle( CallbackBase* callback )
+void Adaptor::RemoveIdle(CallbackBase* callback)
{
- mImpl->RemoveIdle( callback );
+ mImpl->RemoveIdle(callback);
}
-void Adaptor::ReplaceSurface( Window window, Dali::RenderSurfaceInterface& surface )
+void Adaptor::ReplaceSurface(Window window, Dali::RenderSurfaceInterface& surface)
{
}
-void Adaptor::ReplaceSurface( Dali::Integration::SceneHolder window, Dali::RenderSurfaceInterface& surface )
+void Adaptor::ReplaceSurface(Dali::Integration::SceneHolder window, Dali::RenderSurfaceInterface& surface)
{
}
return window;
}
-Any Adaptor::GetNativeWindowHandle( Actor actor )
+Any Adaptor::GetNativeWindowHandle(Actor actor)
{
return GetNativeWindowHandle();
}
{
}
-void Adaptor::SetRenderRefreshRate( unsigned int numberOfVSyncsPerRender )
+void Adaptor::SetRenderRefreshRate(unsigned int numberOfVSyncsPerRender)
{
}
{
}
-void Adaptor::FeedTouchPoint( TouchPoint& point, int timeStamp )
+void Adaptor::FeedTouchPoint(TouchPoint& point, int timeStamp)
{
}
-void Adaptor::FeedWheelEvent( WheelEvent& wheelEvent )
+void Adaptor::FeedWheelEvent(WheelEvent& wheelEvent)
{
}
-void Adaptor::FeedKeyEvent( KeyEvent& keyEvent )
+void Adaptor::FeedKeyEvent(KeyEvent& keyEvent)
{
}
}
};
-LogFactory* gLogFactory = NULL;
+LogFactory* gLogFactory = NULL;
const LogFactoryInterface& Adaptor::GetLogFactory()
{
- if( gLogFactory == NULL )
+ if(gLogFactory == NULL)
{
gLogFactory = new LogFactory;
}
return *gLogFactory;
}
-void Adaptor::RegisterProcessor( Integration::Processor& processor, bool postProcessor)
+class TraceFactory : public TraceFactoryInterface
+{
+public:
+ virtual void InstallTraceFunction() const
+ {
+ Dali::Integration::Trace::LogContextFunction logContextFunction(&TestApplication::LogContext);
+ Dali::Integration::Trace::InstallLogContextFunction(logContextFunction);
+ }
+
+ TraceFactory()
+ {
+ }
+ virtual ~TraceFactory()
+ {
+ }
+};
+
+TraceFactory* gTraceFactory = NULL;
+const TraceFactoryInterface& Adaptor::GetTraceFactory()
+{
+ if(gTraceFactory == NULL)
+ {
+ gTraceFactory = new TraceFactory;
+ }
+ return *gTraceFactory;
+}
+
+void Adaptor::RegisterProcessor(Integration::Processor& processor, bool postProcessor)
{
- mImpl->RegisterProcessor( processor, postProcessor );
+ mImpl->RegisterProcessor(processor, postProcessor);
}
-void Adaptor::UnregisterProcessor( Integration::Processor& processor, bool postProcessor)
+void Adaptor::UnregisterProcessor(Integration::Processor& processor, bool postProcessor)
{
- mImpl->UnregisterProcessor( processor, postProcessor );
+ mImpl->UnregisterProcessor(processor, postProcessor);
}
} // namespace Dali
--- /dev/null
+/*
+ * 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.
+ *
+ */
+
+// CLASS HEADER
+#include <toolkit-texture-upload-manager.h>
+
+// EXTERNAL INCLUDE
+#include <dali/devel-api/adaptor-framework/texture-upload-manager.h>
+#include <dali/graphics-api/graphics-controller.h>
+#include <dali/integration-api/pixel-data-integ.h>
+#include <dali/integration-api/texture-integ.h>
+
+// INTERNAL INCLUDE
+#include <test-graphics-controller.h>
+#include <toolkit-application.h>
+
+namespace Dali
+{
+namespace Internal
+{
+namespace Adaptor
+{
+class TextureUploadManager : public Dali::BaseObject
+{
+public:
+ using ResourceId = Dali::Devel::TextureUploadManager::ResourceId;
+
+public:
+ static Dali::Devel::TextureUploadManager Get();
+ TextureUploadManager();
+ ~TextureUploadManager() = default;
+
+ Dali::Texture GenerateTexture2D();
+
+public: // Update thread called method
+ bool ResourceUpload();
+
+ void InitalizeGraphicsController(Dali::Graphics::Controller& graphicsController);
+
+private: // Update thread called method
+ using UploadRequestItem = std::pair<ResourceId, Dali::PixelData>; ///< TODO : PixelData? PixelBuffer?
+ using RequestUploadQueue = std::vector<UploadRequestItem>;
+
+ bool ProcessUploadQueue(RequestUploadQueue&& queue);
+
+public: // Worker thread called method
+ /**
+ * @copydoc Dali::Devel::TextureUploadManager::RequestUpload()
+ */
+ void RequestUpload(ResourceId id, Dali::PixelData pixelData);
+
+private:
+ Dali::Graphics::Controller* mGraphicsController;
+ RequestUploadQueue mRequestUploadQueue{};
+
+public:
+ ResourceId gUniqueResourceId{0u};
+};
+
+inline Internal::Adaptor::TextureUploadManager& GetImplementation(Dali::Devel::TextureUploadManager& obj)
+{
+ DALI_ASSERT_ALWAYS(obj && "TextureUploadManager is empty");
+
+ Dali::BaseObject& handle = obj.GetBaseObject();
+
+ return static_cast<Internal::Adaptor::TextureUploadManager&>(handle);
+}
+
+inline const Internal::Adaptor::TextureUploadManager& GetImplementation(const Dali::Devel::TextureUploadManager& obj)
+{
+ DALI_ASSERT_ALWAYS(obj && "TextureUploadManager is empty");
+
+ const Dali::BaseObject& handle = obj.GetBaseObject();
+
+ return static_cast<const Internal::Adaptor::TextureUploadManager&>(handle);
+}
+
+/********************************************************************************/
+/********************************* INTERNAL CLASS *****************************/
+/********************************************************************************/
+
+namespace
+{
+Devel::TextureUploadManager gTextureUploadManager;
+} // namespace
+
+Devel::TextureUploadManager TextureUploadManager::Get()
+{
+ if(!gTextureUploadManager)
+ {
+ gTextureUploadManager = Devel::TextureUploadManager(new TextureUploadManager());
+ }
+ return gTextureUploadManager;
+}
+
+TextureUploadManager::TextureUploadManager()
+: mGraphicsController{nullptr}
+{
+}
+
+Dali::Texture TextureUploadManager::GenerateTexture2D()
+{
+ ResourceId resourceId = ++gUniqueResourceId;
+
+ Dali::Texture ret = Dali::Integration::NewTextureWithResourceId(Dali::TextureType::TEXTURE_2D, resourceId);
+
+ return ret;
+}
+
+// Called by update thread
+
+bool TextureUploadManager::ResourceUpload()
+{
+ DALI_ASSERT_DEBUG(mGraphicsController && "GraphicsController is not prepared!");
+
+ // Upload.
+ bool uploaded = ProcessUploadQueue(std::move(mRequestUploadQueue));
+ mRequestUploadQueue.clear();
+
+ return uploaded;
+}
+
+void TextureUploadManager::InitalizeGraphicsController(Dali::Graphics::Controller& graphicsController)
+{
+ mGraphicsController = &graphicsController;
+}
+
+bool TextureUploadManager::ProcessUploadQueue(RequestUploadQueue&& queue)
+{
+ bool uploaded = false;
+
+ if(!queue.empty())
+ {
+ for(auto& requests : queue)
+ {
+ auto& resourceId = requests.first;
+ auto& pixelData = requests.second;
+
+ Graphics::Texture* graphicsTexture = nullptr;
+
+ // TODO : Could we detect TEXTURE_2D or TEXTURE_CUBE case in future?
+ {
+ // We always need to create new one
+ auto createInfo = Graphics::TextureCreateInfo();
+ createInfo
+ .SetTextureType(Dali::Graphics::ConvertTextureType(Dali::TextureType::TEXTURE_2D))
+ .SetUsageFlags(static_cast<Graphics::TextureUsageFlags>(Graphics::TextureUsageFlagBits::SAMPLE))
+ .SetFormat(Dali::Graphics::ConvertPixelFormat(pixelData.GetPixelFormat()))
+ .SetSize({pixelData.GetWidth(), pixelData.GetHeight()})
+ .SetLayout(Graphics::TextureLayout::LINEAR)
+ .SetData(nullptr)
+ .SetDataSize(0u)
+ .SetNativeImage(nullptr)
+ .SetMipMapFlag(Graphics::TextureMipMapFlag::DISABLED);
+
+ graphicsTexture = mGraphicsController->CreateTextureByResourceId(resourceId, createInfo);
+ }
+
+ if(graphicsTexture)
+ {
+ Graphics::TextureUpdateInfo info{};
+
+ info.dstTexture = graphicsTexture;
+ info.dstOffset2D = {0u, 0u};
+ info.layer = 0u;
+ info.level = 0u;
+ info.srcReference = 0;
+ info.srcExtent2D = {pixelData.GetWidth(), pixelData.GetHeight()};
+ info.srcOffset = 0;
+ info.srcSize = Dali::Integration::GetPixelDataBuffer(pixelData).bufferSize;
+ info.srcStride = pixelData.GetStride();
+ info.srcFormat = Dali::Graphics::ConvertPixelFormat(pixelData.GetPixelFormat());
+
+ Graphics::TextureUpdateSourceInfo updateSourceInfo{};
+ updateSourceInfo.sourceType = Graphics::TextureUpdateSourceInfo::Type::PIXEL_DATA;
+ updateSourceInfo.pixelDataSource.pixelData = pixelData;
+
+ mGraphicsController->UpdateTextures({info}, {updateSourceInfo});
+
+ uploaded = true;
+ }
+ else
+ {
+ // Invalidate resouce id! ignore.
+ }
+ }
+
+ if(uploaded)
+ {
+ // Flush here
+ Graphics::SubmitInfo submitInfo;
+ submitInfo.cmdBuffer.clear(); // Only flush
+ submitInfo.flags = 0 | Graphics::SubmitFlagBits::FLUSH;
+ mGraphicsController->SubmitCommandBuffers(submitInfo);
+ }
+ }
+
+ return uploaded;
+}
+
+// Called by worker thread
+
+void TextureUploadManager::RequestUpload(Dali::Devel::TextureUploadManager::ResourceId resourceId, Dali::PixelData pixelData)
+{
+ mRequestUploadQueue.push_back(std::move(UploadRequestItem(resourceId, pixelData)));
+}
+
+} // namespace Adaptor
+
+} // namespace Internal
+
+/********************************************************************************/
+/********************************* PUBLIC CLASS *******************************/
+/********************************************************************************/
+
+namespace Devel
+{
+// Called by main thread
+
+TextureUploadManager::TextureUploadManager() = default;
+
+TextureUploadManager::~TextureUploadManager() = default;
+
+TextureUploadManager TextureUploadManager::Get()
+{
+ return Internal::Adaptor::TextureUploadManager::Get();
+}
+
+Dali::Texture TextureUploadManager::GenerateTexture2D()
+{
+ return Internal::Adaptor::GetImplementation(*this).GenerateTexture2D();
+}
+
+TextureUploadManager::TextureUploadManager(Internal::Adaptor::TextureUploadManager* impl)
+: BaseHandle(impl)
+{
+}
+
+// Called by update thread
+
+bool TextureUploadManager::ResourceUpload()
+{
+ return Internal::Adaptor::GetImplementation(*this).ResourceUpload();
+}
+
+// Called by worker thread
+
+void TextureUploadManager::RequestUpload(ResourceId resourceId, PixelData pixelData)
+{
+ Internal::Adaptor::GetImplementation(*this).RequestUpload(resourceId, pixelData);
+}
+
+} // namespace Devel
+
+} // namespace Dali
+
+namespace Test
+{
+namespace TextureUploadManager
+{
+void InitalizeGraphicsController(Dali::Graphics::Controller& graphicsController)
+{
+ auto textureUploadManager = Dali::Devel::TextureUploadManager::Get();
+ Internal::Adaptor::GetImplementation(textureUploadManager).InitalizeGraphicsController(graphicsController);
+}
+} // namespace TextureUploadManager
+} // namespace Test
--- /dev/null
+#ifndef DALI_TOOLKIT_TOOLKIT_TEXTURE_UPLOAD_MANAGER_H
+#define DALI_TOOLKIT_TOOLKIT_TEXTURE_UPLOAD_MANAGER_H
+
+/*
+ * 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.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/devel-api/adaptor-framework/texture-upload-manager.h>
+
+namespace Dali
+{
+namespace Graphics DALI_INTERNAL
+{
+class Controller;
+} // namespace DALI_INTERNAL
+} // namespace Dali
+
+namespace Test
+{
+namespace TextureUploadManager
+{
+void InitalizeGraphicsController(Dali::Graphics::Controller& graphicsController);
+}
+} // namespace Test
+
+#endif // DALI_TOOLKIT_TOOLKIT_TEXTURE_UPLOAD_MANAGER_H
#include <iostream>
#include <vector>
+#include <unistd.h>
+#include <thread>
+
#include <dali-toolkit-test-suite-utils.h>
#include <toolkit-environment-variable.h>
#include <toolkit-event-thread-callback.h>
+#include <toolkit-texture-upload-manager.h>
#include <toolkit-timer.h>
#include <dali-toolkit/dali-toolkit.h>
#include <dali-toolkit/devel-api/image-loader/texture-manager.h>
#include <dali-toolkit/devel-api/visual-factory/transition-data.h>
#include <dali-toolkit/devel-api/visual-factory/visual-factory.h>
+#include <dali-toolkit/devel-api/visuals/image-visual-actions-devel.h>
#include <dali-toolkit/devel-api/visuals/image-visual-properties-devel.h>
#include <dali-toolkit/public-api/image-loader/image-url.h>
#include <dali-toolkit/public-api/image-loader/image.h>
+#include <dali/devel-api/adaptor-framework/texture-upload-manager.h>
+
#include "dummy-control.h"
#include "test-encoded-image-buffer.h"
#include "test-native-image-source.h"
END_TEST;
}
+
+int UtcDaliImageVisualLoadFastTrackImage01(void)
+{
+ tet_infoline("Test worker thread uploading with Local URL");
+ ToolkitTestApplication application;
+
+ Test::TextureUploadManager::InitalizeGraphicsController(application.GetGraphicsController());
+
+ VisualFactory factory = VisualFactory::Get();
+ DALI_TEST_CHECK(factory);
+
+ // Pair of filename - expect GenTextures count.
+ std::vector<std::pair<std::string, int>> testCases = {
+ {TEST_IMAGE_FILE_NAME, 1},
+ {TEST_REMOTE_IMAGE_FILE_NAME, 1},
+ {TEST_INVALID_FILE_NAME, 0},
+ };
+
+ for(auto&& tc : testCases)
+ {
+ auto& filename = tc.first;
+ auto& expectValue = tc.second;
+
+ tet_printf("Test %s\n", filename.c_str());
+
+ Property::Map propertyMap;
+ propertyMap.Insert(Toolkit::Visual::Property::TYPE, Visual::IMAGE);
+ propertyMap.Insert(ImageVisual::Property::URL, filename.c_str());
+ propertyMap.Insert(DevelImageVisual::Property::FAST_TRACK_UPLOADING, true);
+
+ Visual::Base visual = factory.CreateVisual(propertyMap);
+ DALI_TEST_CHECK(visual);
+
+ DummyControl actor = DummyControl::New();
+ DummyControlImpl& dummyImpl = static_cast<DummyControlImpl&>(actor.GetImplementation());
+ dummyImpl.RegisterVisual(Control::CONTROL_PROPERTY_END_INDEX + 1, visual);
+ actor.SetProperty(Actor::Property::SIZE, Vector2(200.f, 200.f));
+
+ TestGlAbstraction& gl = application.GetGlAbstraction();
+ TraceCallStack& textureTrace = gl.GetTextureTrace();
+ textureTrace.Enable(true);
+
+ application.GetScene().Add(actor);
+
+ application.SendNotification();
+ application.Render();
+
+ // EventThread without callback
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1, 30, false), true, TEST_LOCATION);
+
+ DALI_TEST_EQUALS(textureTrace.CountMethod("GenTextures"), 0, TEST_LOCATION);
+
+ {
+ // TODO : There is no way to flush TextureUploadManager in test-application's Render() now.
+ // How can we make it? Should it be integration-api?
+ auto textureUploadManager = Dali::Devel::TextureUploadManager::Get();
+ DALI_TEST_EQUALS(textureUploadManager.ResourceUpload(), expectValue > 0, TEST_LOCATION);
+ }
+ // Render only without SendNotification(). And check whether glTexImage2D called or not.
+ application.Render();
+
+ DALI_TEST_EQUALS(textureTrace.CountMethod("GenTextures"), expectValue, TEST_LOCATION);
+
+ application.SendNotification();
+ application.Render();
+
+ textureTrace.Reset();
+ }
+
+ END_TEST;
+}
+
+int UtcDaliImageVisualLoadFastTrackImage02(void)
+{
+ tet_infoline("Test worker thread uploading with Local URL");
+ ToolkitTestApplication application;
+
+ Test::TextureUploadManager::InitalizeGraphicsController(application.GetGraphicsController());
+
+ VisualFactory factory = VisualFactory::Get();
+ DALI_TEST_CHECK(factory);
+
+ {
+ auto filename = std::string(TEST_IMAGE_FILE_NAME);
+ auto expectValue = 1;
+
+ tet_printf("Test %s\n", filename.c_str());
+
+ Property::Map propertyMap;
+ propertyMap.Insert(Toolkit::Visual::Property::TYPE, Visual::IMAGE);
+ propertyMap.Insert(ImageVisual::Property::URL, filename.c_str());
+ propertyMap.Insert("fastTrackUploading", true);
+
+ Visual::Base visual = factory.CreateVisual(propertyMap);
+ DALI_TEST_CHECK(visual);
+
+ DummyControl actor = DummyControl::New();
+ DummyControlImpl& dummyImpl = static_cast<DummyControlImpl&>(actor.GetImplementation());
+ dummyImpl.RegisterVisual(Control::CONTROL_PROPERTY_END_INDEX + 1, visual);
+ actor.SetProperty(Actor::Property::SIZE, Vector2(200.f, 200.f));
+
+ TestGlAbstraction& gl = application.GetGlAbstraction();
+ TraceCallStack& textureTrace = gl.GetTextureTrace();
+ textureTrace.Enable(true);
+
+ application.GetScene().Add(actor);
+
+ application.SendNotification();
+ application.Render();
+
+ // EventThread without callback
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1, 30, false), true, TEST_LOCATION);
+
+ DALI_TEST_EQUALS(textureTrace.CountMethod("GenTextures"), 0, TEST_LOCATION);
+
+ {
+ // TODO : There is no way to flush TextureUploadManager in test-application's Render() now.
+ // How can we make it? Should it be integration-api?
+ auto textureUploadManager = Dali::Devel::TextureUploadManager::Get();
+ DALI_TEST_EQUALS(textureUploadManager.ResourceUpload(), expectValue > 0, TEST_LOCATION);
+ }
+ // Render only without SendNotification(). And check whether glTexImage2D called or not.
+ application.Render();
+
+ DALI_TEST_EQUALS(textureTrace.CountMethod("GenTextures"), expectValue, TEST_LOCATION);
+
+ application.SendNotification();
+ application.Render();
+
+ textureTrace.Reset();
+ }
+
+ END_TEST;
+}
+
+int UtcDaliImageVisualLoadFastTrackImageResourceReady(void)
+{
+ tet_infoline("Test worker thread uploading with Local URL");
+ ToolkitTestApplication application;
+
+ VisualFactory factory = VisualFactory::Get();
+ DALI_TEST_CHECK(factory);
+
+ Property::Map propertyMap;
+ propertyMap.Insert(Toolkit::Visual::Property::TYPE, Visual::IMAGE);
+ propertyMap.Insert(ImageVisual::Property::URL, TEST_IMAGE_FILE_NAME);
+ propertyMap.Insert(DevelImageVisual::Property::FAST_TRACK_UPLOADING, true);
+
+ Visual::Base visual = factory.CreateVisual(propertyMap);
+ DALI_TEST_CHECK(visual);
+
+ DummyControl actor = DummyControl::New();
+ DummyControlImpl& dummyImpl = static_cast<DummyControlImpl&>(actor.GetImplementation());
+ dummyImpl.RegisterVisual(Control::CONTROL_PROPERTY_END_INDEX + 1, visual);
+ actor.SetProperty(Actor::Property::SIZE, Vector2(200.f, 200.f));
+
+ TestGlAbstraction& gl = application.GetGlAbstraction();
+ TraceCallStack& textureTrace = gl.GetTextureTrace();
+ textureTrace.Enable(true);
+
+ application.GetScene().Add(actor);
+
+ application.SendNotification();
+ application.Render();
+
+ // EventThread with callback
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+
+ // Check resource ready comes after
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS(actor.GetRendererCount(), 1u, TEST_LOCATION);
+ DALI_TEST_EQUALS(actor.IsResourceReady(), true, TEST_LOCATION);
+
+ END_TEST;
+}
+
+int UtcDaliImageVisualLoadFastTrackImageReload(void)
+{
+ tet_infoline("Test worker thread uploading with Local URL");
+ ToolkitTestApplication application;
+
+ Test::TextureUploadManager::InitalizeGraphicsController(application.GetGraphicsController());
+
+ VisualFactory factory = VisualFactory::Get();
+ DALI_TEST_CHECK(factory);
+
+ Property::Map propertyMap;
+ propertyMap.Insert(Toolkit::Visual::Property::TYPE, Visual::IMAGE);
+ propertyMap.Insert(ImageVisual::Property::URL, TEST_IMAGE_FILE_NAME);
+ propertyMap.Insert(DevelImageVisual::Property::FAST_TRACK_UPLOADING, true);
+
+ Visual::Base visual = factory.CreateVisual(propertyMap);
+ DALI_TEST_CHECK(visual);
+
+ DummyControl actor = DummyControl::New();
+ DummyControlImpl& dummyImpl = static_cast<DummyControlImpl&>(actor.GetImplementation());
+ dummyImpl.RegisterVisual(Control::CONTROL_PROPERTY_END_INDEX + 1, visual);
+ actor.SetProperty(Actor::Property::SIZE, Vector2(200.f, 200.f));
+
+ TestGlAbstraction& gl = application.GetGlAbstraction();
+ TraceCallStack& textureTrace = gl.GetTextureTrace();
+ textureTrace.Enable(true);
+
+ application.GetScene().Add(actor);
+
+ application.SendNotification();
+ application.Render();
+
+ // EventThread without callback
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1, 30, false), true, TEST_LOCATION);
+
+ DALI_TEST_EQUALS(textureTrace.CountMethod("GenTextures"), 0, TEST_LOCATION);
+
+ {
+ // TODO : There is no way to flush TextureUploadManager in test-application's Render() now.
+ // How can we make it? Should it be integration-api?
+ auto textureUploadManager = Dali::Devel::TextureUploadManager::Get();
+ DALI_TEST_EQUALS(textureUploadManager.ResourceUpload(), true, TEST_LOCATION);
+ }
+ // Render only without SendNotification(). And check whether glTexImage2D called or not.
+ application.Render();
+
+ DALI_TEST_EQUALS(textureTrace.CountMethod("GenTextures"), 1, TEST_LOCATION);
+
+ // Reload
+ Property::Map attributes;
+ DevelControl::DoAction(actor, Control::CONTROL_PROPERTY_END_INDEX + 1, DevelImageVisual::Action::RELOAD, attributes);
+
+ // EventThread with callback
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+
+ // Check resource ready comes after
+ application.SendNotification();
+ application.Render();
+
+ // Check whether renderer count is 1 or not.
+ DALI_TEST_EQUALS(actor.GetRendererCount(), 1u, TEST_LOCATION);
+ DALI_TEST_EQUALS(actor.IsResourceReady(), true, TEST_LOCATION);
+
+ END_TEST;
+}
+
+int UtcDaliImageVisualLoadFastTrackImagePlanes01(void)
+{
+#if 0 //< Do not open this UTC yet.
+ EnvironmentVariable::SetTestEnvironmentVariable(LOAD_IMAGE_YUV_PLANES_ENV, "1");
+ EnvironmentVariable::SetTestEnvironmentVariable(ENABLE_DECODE_JPEG_TO_YUV_420_ENV, "1");
+
+ ToolkitTestApplication application;
+
+ Test::TextureUploadManager::InitalizeGraphicsController(application.GetGraphicsController());
+
+ VisualFactory factory = VisualFactory::Get();
+ DALI_TEST_CHECK(factory);
+
+ Property::Map propertyMap;
+ propertyMap.Insert(Toolkit::Visual::Property::TYPE, Visual::IMAGE);
+ propertyMap.Insert(ImageVisual::Property::URL, TEST_YUV420_IMAGE_FILE_NAME);
+ propertyMap.Insert(DevelImageVisual::Property::FAST_TRACK_UPLOADING, true);
+
+ Visual::Base visual = factory.CreateVisual(propertyMap);
+ DALI_TEST_CHECK(visual);
+
+ DummyControl actor = DummyControl::New();
+ DummyControlImpl& dummyImpl = static_cast<DummyControlImpl&>(actor.GetImplementation());
+ dummyImpl.RegisterVisual(Control::CONTROL_PROPERTY_END_INDEX + 1, visual);
+ actor.SetProperty(Actor::Property::SIZE, Vector2(200.f, 200.f));
+
+ TestGlAbstraction& gl = application.GetGlAbstraction();
+ TraceCallStack& textureTrace = gl.GetTextureTrace();
+ textureTrace.Enable(true);
+
+ application.GetScene().Add(actor);
+
+ application.SendNotification();
+ application.Render();
+
+ // EventThread without callback
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1, 30, false), true, TEST_LOCATION);
+
+ DALI_TEST_EQUALS(textureTrace.CountMethod("GenTextures"), 0, TEST_LOCATION);
+
+ {
+ // TODO : There is no way to flush TextureUploadManager in test-application's Render() now.
+ // How can we make it? Should it be integration-api?
+ auto textureUploadManager = Dali::Devel::TextureUploadManager::Get();
+ textureUploadManager.ResourceUpload();
+ application.Render();
+ }
+ // Render only without SendNotification(). And check whether glTexImage2D called or not.
+ application.Render();
+
+ DALI_TEST_EQUALS(textureTrace.CountMethod("GenTextures"), 3, TEST_LOCATION);
+
+ // Event thread don't know the result yet.
+ DALI_TEST_EQUALS(actor.IsResourceReady(), false, TEST_LOCATION);
+
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+
+ // Check resource ready comes after
+ application.SendNotification();
+
+ DALI_TEST_EQUALS(actor.GetRendererCount(), 1u, TEST_LOCATION);
+ DALI_TEST_EQUALS(actor.IsResourceReady(), true, TEST_LOCATION);
+
+#else
+ DALI_TEST_CHECK(true);
+#endif
+ END_TEST;
+}
\ No newline at end of file
END_TEST;
}
+int UtcDaliParticleSystemEmitterNew2(void)
+{
+ // create particle emitter
+ auto emitter = ParticleEmitter::New();
+
+ bool result = (emitter != nullptr);
+ DALI_TEST_EQUALS(result, true, TEST_LOCATION);
+
+ // Create test source
+ auto source = ParticleSource::New<TestSource>(&emitter);
+
+ // Create test renderer
+ auto renderer = ParticleRenderer::New();
+
+ // Create modifier
+ auto modifier = ParticleModifier::New<TestModifier>();
+
+ // Create domain
+ auto domain = ParticleDomain::New();
+
+ // Test emitter readiness
+ auto ready = emitter.GetStatus();
+
+ // Emitter should return status incomplete
+ DALI_TEST_EQUALS(ready, ParticleEmitter::Status::INCOMPLETE, TEST_LOCATION);
+
+ // Attach all components to the emitter
+ emitter.SetSource(source);
+ emitter.SetRenderer(renderer);
+ emitter.AddModifier(modifier);
+ emitter.SetDomain(domain);
+
+ // test blending mode
+ DALI_TEST_EQUALS(renderer.GetBlendingMode(), Dali::Toolkit::ParticleSystem::BlendingMode::DEFAULT, TEST_LOCATION);
+
+ emitter.SetParticleCount(10000);
+ DALI_TEST_EQUALS(emitter.GetParticleCount(), 10000, TEST_LOCATION);
+
+ auto m = emitter.GetModifierAt(0);
+ DALI_TEST_EQUALS(m != nullptr, true, TEST_LOCATION);
+
+ m.GetModifierCallback();
+
+ // test status again (domain is optional);
+ ready = emitter.GetStatus();
+
+ // Emitter should return status incomplete
+ DALI_TEST_EQUALS(ready, ParticleEmitter::Status::READY, TEST_LOCATION);
+
+ END_TEST;
+}
+
+int UtcDaliParticleSystemEmitterDefaultStreams(void)
+{
+ // create particle emitter
+ auto emitter = ParticleEmitter::New();
+
+ bool result = (emitter != nullptr);
+ DALI_TEST_EQUALS(result, true, TEST_LOCATION);
+
+ // Create test source
+ auto source = ParticleSource::New<TestSource>(&emitter);
+
+ // Create test renderer
+ auto renderer = ParticleRenderer::New();
+
+ // Create modifier
+ auto modifier = ParticleModifier::New<TestModifier>();
+
+ // Create domain
+ auto domain = ParticleDomain::New();
+
+ // Test emitter readiness
+ auto ready = emitter.GetStatus();
+
+ // Emitter should return status incomplete
+ DALI_TEST_EQUALS(ready, ParticleEmitter::Status::INCOMPLETE, TEST_LOCATION);
+
+ // Attach all components to the emitter
+ emitter.SetSource(source);
+ emitter.SetRenderer(renderer);
+ emitter.AddModifier(modifier);
+ emitter.SetDomain(domain);
+
+ auto particleList = emitter.GetParticleList();
+ std::vector<uint32_t> expectedValues = {
+ ParticleStream::POSITION_STREAM_BIT, 0, ParticleStream::COLOR_STREAM_BIT, 3, ParticleStream::VELOCITY_STREAM_BIT, 2, ParticleStream::SCALE_STREAM_BIT, 1, ParticleStream::LIFETIME_STREAM_BIT, 4, ParticleStream::LIFETIME_BASE_STREAM_BIT, 5};
+
+ for(auto i = 0u; i < expectedValues.size(); i += 2)
+ {
+ auto index = particleList.GetDefaultStreamIndex(expectedValues[i]);
+ DALI_TEST_EQUALS(index, expectedValues[i + 1], TEST_LOCATION);
+ }
+
+ // test status again (domain is optional);
+ ready = emitter.GetStatus();
+
+ // Emitter should return status incomplete
+ DALI_TEST_EQUALS(ready, ParticleEmitter::Status::READY, TEST_LOCATION);
+
+ END_TEST;
+}
+
int UtcDaliParticleSystemEmitterModifierStack(void)
{
// create particle emitter
if( NOT LIB_DIR )
set( LIB_DIR ${prefix}/lib )
endif()
+ set(DEV_INCLUDE_PATH ${prefix}/include/bullet)
set(bullet_pkg_cfg_file bullet3.pc)
configure_file(${CMAKE_CURRENT_LIST_DIR}/${bullet_pkg_cfg_file}.cmake ${bullet_pkg_cfg_file} @ONLY)
include(\${CMAKE_CURRENT_LIST_DIR}/bullet3-targets.cmake)
")
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/bullet3-config.cmake DESTINATION share/bullet3)
-endif()
\ No newline at end of file
+endif()
MASKING_TYPE = ORIENTATION_CORRECTION + 12,
/**
+ * @brief If true, uploads texture before ResourceReady signal is emitted. Otherwise uploads after texture load is completed.
+ * @details Name "fastTrackUploading", type Property::BOOLEAN
+ * If true, the upload happens without event-thread dependency, but the following need to be considered:
+ * - Texture size is not valid until upload is fully complete.
+ * - Texture cannot be cached (a new image is uploaded every time).
+ * - Seamless visual change is not supported.
+ * - The following, if set are also not supported and will be ignored:
+ * - Alpha masking
+ * - Synchronous loading
+ * - Reload action
+ * - Atlas loading
+ * - Custom shader
+ * @note Used by the ImageVisual. The default is false.
+ */
+ FAST_TRACK_UPLOADING = ORIENTATION_CORRECTION + 13,
+
+ /**
* @brief Whether to enable broken image in image visual.
* Some of visual don't need to show broken image(ex. placeholder)
* Disable broken image for these visuals.
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * 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.
GlViewRenderThread::GlViewRenderThread(Dali::NativeImageSourceQueuePtr queue)
: mLogFactory(Dali::Adaptor::Get().GetLogFactory()),
+ mTraceFactory(Dali::Adaptor::Get().GetTraceFactory()),
mSurfaceSize(1, 1),
mNativeImageSurface(),
mNativeImageQueue(queue),
{
Dali::SetThreadName("GlViewRenderer");
mLogFactory.InstallLogFunction();
+ mTraceFactory.InstallTraceFunction();
int renderFrameResult = 0;
#define DALI_TOOLKIT_INTERNAL_GL_VIEW_THREAD_H
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * 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.
#include <dali/devel-api/threading/thread.h>
#include <dali/integration-api/adaptor-framework/log-factory-interface.h>
#include <dali/integration-api/adaptor-framework/native-image-surface.h>
+#include <dali/integration-api/adaptor-framework/trace-factory-interface.h>
#include <dali/public-api/math/vector2.h>
#include <dali/public-api/signals/callback.h>
void SleepUntil(uint64_t timeInNanoseconds);
private:
- const Dali::LogFactoryInterface& mLogFactory;
- Dali::Vector2 mSurfaceSize; ///< The size of mNativeImageQueue
- Dali::NativeImageSurfacePtr mNativeImageSurface;
- Dali::NativeImageSourceQueuePtr mNativeImageQueue;
- Semaphore<> mSurfaceSemaphore; ///< The semaphore to avoid race condition to the render target
+ const Dali::LogFactoryInterface& mLogFactory;
+ const Dali::TraceFactoryInterface& mTraceFactory;
+
+ Dali::Vector2 mSurfaceSize; ///< The size of mNativeImageQueue
+ Dali::NativeImageSurfacePtr mNativeImageSurface;
+ Dali::NativeImageSourceQueuePtr mNativeImageQueue;
+ Semaphore<> mSurfaceSemaphore; ///< The semaphore to avoid race condition to the render target
std::unique_ptr<CallbackBase> mGlInitCallback;
std::unique_ptr<CallbackBase> mGlRenderFrameCallback;
${toolkit_src_dir}/filters/spread-filter.cpp
${toolkit_src_dir}/image-loader/async-image-loader-impl.cpp
${toolkit_src_dir}/image-loader/atlas-packer.cpp
+ ${toolkit_src_dir}/image-loader/fast-track-loading-task.cpp
${toolkit_src_dir}/image-loader/image-atlas-impl.cpp
${toolkit_src_dir}/image-loader/loading-task.cpp
${toolkit_src_dir}/image-loader/image-url-impl.cpp
--- /dev/null
+/*
+ * 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.
+ *
+ */
+
+// CLASS HEADER
+#include <dali-toolkit/internal/image-loader/fast-track-loading-task.h>
+
+// EXTERNAL INCLUDES
+#include <dali/devel-api/adaptor-framework/image-loading.h>
+#include <dali/devel-api/adaptor-framework/texture-upload-manager.h>
+#include <dali/integration-api/debug.h>
+#include <dali/integration-api/texture-integ.h>
+#include <dali/integration-api/trace.h>
+
+#ifdef TRACE_ENABLED
+#include <sstream>
+#endif
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+namespace
+{
+DALI_INIT_TRACE_FILTER(gTraceFilter, DALI_TRACE_IMAGE_PERFORMANCE_MARKER, false);
+}
+
+FastTrackLoadingTask::FastTrackLoadingTask(const VisualUrl& url, ImageDimensions dimensions, FittingMode::Type fittingMode, SamplingMode::Type samplingMode, bool orientationCorrection, DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad, CallbackBase* callback)
+: AsyncTask(MakeCallback(this, &FastTrackLoadingTask::OnComplete), url.GetProtocolType() == VisualUrl::ProtocolType::REMOTE ? AsyncTask::PriorityType::LOW : AsyncTask::PriorityType::HIGH),
+ mUrl(url),
+ mTexture(),
+ mDimensions(dimensions),
+ mFittingMode(fittingMode),
+ mSamplingMode(samplingMode),
+ mPreMultiplyOnLoad(preMultiplyOnLoad),
+ mCallback(),
+ mTextureUploadManager(Dali::Devel::TextureUploadManager::Get()),
+ mImageWidth(0u),
+ mImageHeight(0u),
+ mImageFormat(Pixel::INVALID),
+ mPixelData(),
+ mResourceId(0u),
+ mOrientationCorrection(orientationCorrection),
+ mLoadSuccess(false),
+ mPremultiplied(false)
+{
+ mCallback = std::unique_ptr<CallbackBase>(callback);
+ PrepareTexture();
+}
+
+FastTrackLoadingTask::~FastTrackLoadingTask()
+{
+}
+
+void FastTrackLoadingTask::PrepareTexture()
+{
+ mTexture = mTextureUploadManager.GenerateTexture2D();
+ mResourceId = Integration::GetTextureResourceId(mTexture);
+}
+
+void FastTrackLoadingTask::OnComplete(AsyncTaskPtr task)
+{
+ if(mLoadSuccess)
+ {
+ Dali::Integration::SetTextureSize(mTexture, Dali::ImageDimensions(mImageWidth, mImageHeight));
+ Dali::Integration::SetTexturePixelFormat(mTexture, mImageFormat);
+ }
+ if(mCallback)
+ {
+ CallbackBase::Execute(*mCallback, FastTrackLoadingTaskPtr(reinterpret_cast<FastTrackLoadingTask*>(task.Get())));
+ }
+}
+
+// Called by worker thread
+
+void FastTrackLoadingTask::Process()
+{
+ Load();
+ UploadToTexture();
+}
+
+bool FastTrackLoadingTask::IsReady()
+{
+ return true;
+}
+
+void FastTrackLoadingTask::Load()
+{
+#ifdef TRACE_ENABLED
+ if(gTraceFilter && gTraceFilter->IsTraceEnabled())
+ {
+ std::ostringstream oss;
+ oss << "[url:" << mUrl.GetUrl() << "]";
+ DALI_TRACE_BEGIN_WITH_MESSAGE(gTraceFilter, "DALI_IMAGE_FAST_TRACK_UPLOADING_TASK", oss.str().c_str());
+ }
+#endif
+
+ Devel::PixelBuffer pixelBuffer;
+ std::vector<Devel::PixelBuffer> pixelBuffers;
+
+ if(mUrl.IsValid() && mUrl.IsLocalResource())
+ {
+ // TODO : We need to consider YUV case in future.
+ //Dali::LoadImagePlanesFromFile(mUrl.GetUrl(), pixelBuffers, mDimensions, mFittingMode, mSamplingMode, mOrientationCorrection);
+
+ pixelBuffer = Dali::LoadImageFromFile(mUrl.GetUrl(), mDimensions, mFittingMode, mSamplingMode, mOrientationCorrection);
+ }
+ else if(mUrl.IsValid())
+ {
+ pixelBuffer = Dali::DownloadImageSynchronously(mUrl.GetUrl(), mDimensions, mFittingMode, mSamplingMode, mOrientationCorrection);
+ }
+
+ if(pixelBuffer)
+ {
+ pixelBuffers.push_back(pixelBuffer);
+ }
+
+ if(pixelBuffers.empty())
+ {
+ DALI_LOG_ERROR("FastTrackLoadingTask::Load: Loading is failed: ResourceId : %d, url : [%s]\n", mResourceId, mUrl.GetUrl().c_str());
+ }
+ else
+ {
+ if(pixelBuffers.size() == 1u)
+ {
+ mLoadSuccess = true;
+ MultiplyAlpha(pixelBuffers[0]);
+ mPixelData = Dali::Devel::PixelBuffer::Convert(pixelBuffers[0]);
+ }
+ else
+ {
+ DALI_LOG_ERROR("FastTrackLoadingTask::Load: ??? Undefined case. PixelBuffers.size() : %zu : ResourceId : %d, url : [%s]\n", pixelBuffers.size(), mResourceId, mUrl.GetUrl().c_str());
+ }
+ }
+
+#ifdef TRACE_ENABLED
+ if(gTraceFilter && gTraceFilter->IsTraceEnabled())
+ {
+ std::ostringstream oss;
+ oss << "[";
+ oss << "pixelBuffers: " << pixelBuffers.size() << " ";
+ if(!pixelBuffers.empty())
+ {
+ oss << "premult:" << mPremultiplied << " ";
+ }
+ oss << "url:" << mUrl.GetUrl() << "]";
+ DALI_TRACE_END_WITH_MESSAGE(gTraceFilter, "DALI_IMAGE_FAST_TRACK_UPLOADING_TASK", oss.str().c_str());
+ }
+#endif
+}
+
+void FastTrackLoadingTask::MultiplyAlpha(Dali::Devel::PixelBuffer pixelBuffer)
+{
+ if(mPreMultiplyOnLoad == DevelAsyncImageLoader::PreMultiplyOnLoad::ON && Pixel::HasAlpha(pixelBuffer.GetPixelFormat()))
+ {
+ pixelBuffer.MultiplyColorByAlpha();
+ mPremultiplied = pixelBuffer.IsAlphaPreMultiplied();
+ }
+}
+
+void FastTrackLoadingTask::UploadToTexture()
+{
+ if(mLoadSuccess)
+ {
+ mImageWidth = mPixelData.GetWidth();
+ mImageHeight = mPixelData.GetHeight();
+ mImageFormat = mPixelData.GetPixelFormat();
+
+ mTextureUploadManager.RequestUpload(mResourceId, mPixelData);
+ }
+
+ mPixelData.Reset();
+}
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
--- /dev/null
+#ifndef DALI_TOOLKIT_FAST_TRACK_IMAGE_LOADING_TASK_H
+#define DALI_TOOLKIT_FAST_TRACK_IMAGE_LOADING_TASK_H
+
+/*
+ * 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.
+ */
+
+// EXTERNAL INCLUDES
+#include <dali-toolkit/devel-api/image-loader/async-image-loader-devel.h>
+#include <dali-toolkit/internal/texture-manager/texture-manager-type.h>
+#include <dali-toolkit/internal/visuals/visual-url.h>
+#include <dali/devel-api/adaptor-framework/pixel-buffer.h>
+#include <dali/devel-api/adaptor-framework/texture-upload-manager.h>
+#include <dali/integration-api/adaptor-framework/log-factory-interface.h>
+#include <dali/public-api/adaptor-framework/async-task-manager.h>
+#include <dali/public-api/rendering/texture.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+class FastTrackLoadingTask;
+using FastTrackLoadingTaskPtr = IntrusivePtr<FastTrackLoadingTask>;
+
+/**
+ * @brief The task of loading image and uploading texture on fast track.
+ * It is available that upload the loaded image data on texture at image loader threads.
+ */
+class FastTrackLoadingTask : public AsyncTask
+{
+public:
+ /**
+ * @brief Constructor.
+ */
+ FastTrackLoadingTask(const VisualUrl& url,
+ ImageDimensions dimensions,
+ FittingMode::Type fittingMode,
+ SamplingMode::Type samplingMode,
+ bool orientationCorrection,
+ DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad,
+ CallbackBase* callback);
+
+ /**
+ * @brief Destructor.
+ */
+ ~FastTrackLoadingTask() override;
+
+ /**
+ * @brief Process the task accodring to the type
+ */
+ void Process() override;
+
+ /**
+ * @brief Whether the task is ready to process.
+ * @return True if the task is ready to process.
+ */
+ bool IsReady() override;
+
+private:
+ // Undefined
+ FastTrackLoadingTask(const FastTrackLoadingTask& queue) = delete;
+ FastTrackLoadingTask& operator=(const FastTrackLoadingTask& queue) = delete;
+
+ /**
+ * @brief Create textures for this task.
+ * @note This should be called in construct timing.
+ */
+ void PrepareTexture();
+
+ /**
+ * @brief Load the image.
+ */
+ void Load();
+
+ /**
+ * @brief Multiply alpha if required.
+ *
+ * @param[in,out] pixelBuffer target pixel buffer that need to be multiplied alpha.
+ */
+ void MultiplyAlpha(Dali::Devel::PixelBuffer pixelBuffer);
+
+ /**
+ * @brief Upload loaded pixelBuffer into texture
+ */
+ void UploadToTexture();
+
+private:
+ /**
+ * @brief Complete callback.
+ *
+ * @param[in] task The pointer of task who call this callback.
+ */
+ void OnComplete(AsyncTaskPtr task);
+
+public:
+ VisualUrl mUrl; ///< url of the image to load.
+ Dali::Texture mTexture; ///< texture for regular image.
+
+private:
+ ImageDimensions mDimensions; ///< dimensions to load
+ FittingMode::Type mFittingMode; ///< fitting options
+ SamplingMode::Type mSamplingMode; ///< sampling options
+ DevelAsyncImageLoader::PreMultiplyOnLoad mPreMultiplyOnLoad;
+ std::unique_ptr<CallbackBase> mCallback;
+
+ // Texture Upload relative API
+ Dali::Devel::TextureUploadManager mTextureUploadManager;
+
+ // Note : mPixelData is invalid after upload requested. We should keep image size informations.
+ uint32_t mImageWidth;
+ uint32_t mImageHeight;
+ Pixel::Format mImageFormat;
+
+ Dali::PixelData mPixelData;
+
+ uint32_t mResourceId;
+
+ bool mOrientationCorrection : 1; ///< If orientation correction is needed
+
+public:
+ bool mLoadSuccess : 1; ///< Whether image load successed or not.
+ bool mPremultiplied : 1; ///< True if the image's color was multiplied by it's alpha
+};
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_FAST_TRACK_IMAGE_LOADING_TASK_H
*/
// CLASS HEADER
-#include "loading-task.h"
+#include <dali-toolkit/internal/image-loader/loading-task.h>
// EXTERNAL INCLUDES
#include <dali/devel-api/adaptor-framework/image-loading.h>
#include <dali/devel-api/adaptor-framework/thread-settings.h>
#include <dali/integration-api/adaptor-framework/adaptor.h>
#include <dali/integration-api/debug.h>
+#include <dali/integration-api/trace.h>
#include <dali/public-api/adaptor-framework/encoded-image-buffer.h>
+#ifdef TRACE_ENABLED
+#include <sstream>
+#endif
+
namespace Dali
{
namespace Toolkit
{
namespace Internal
{
+namespace
+{
+DALI_INIT_TRACE_FILTER(gTraceFilter, DALI_TRACE_IMAGE_PERFORMANCE_MARKER, false);
+}
+
LoadingTask::LoadingTask(uint32_t id, Dali::AnimatedImageLoading animatedImageLoading, uint32_t frameIndex, DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad, CallbackBase* callback)
: AsyncTask(callback),
url(),
void LoadingTask::Process()
{
+#ifdef TRACE_ENABLED
+ if(gTraceFilter && gTraceFilter->IsTraceEnabled())
+ {
+ std::ostringstream oss;
+ oss << "[url:" << (!!(animatedImageLoading) ? animatedImageLoading.GetUrl() : url.GetUrl()) << "]";
+ DALI_TRACE_BEGIN_WITH_MESSAGE(gTraceFilter, "DALI_IMAGE_LOADING_TASK", oss.str().c_str());
+ }
+#endif
+
isReady = false;
if(!isMaskTask)
{
}
MultiplyAlpha();
isReady = true;
+
+#ifdef TRACE_ENABLED
+ if(gTraceFilter && gTraceFilter->IsTraceEnabled())
+ {
+ std::ostringstream oss;
+ oss << "[";
+ oss << "masking:" << isMaskTask << " ";
+ oss << "index: " << frameIndex << " ";
+ oss << "pixelBuffers: " << pixelBuffers.size() << " ";
+ if(!pixelBuffers.empty())
+ {
+ oss << "premult:" << pixelBuffers[0].IsAlphaPreMultiplied() << " ";
+ }
+ oss << "url:" << (!!(animatedImageLoading) ? animatedImageLoading.GetUrl() : url.GetUrl()) << "]";
+ DALI_TRACE_END_WITH_MESSAGE(gTraceFilter, "DALI_IMAGE_LOADING_TASK", oss.str().c_str());
+ }
+#endif
}
bool LoadingTask::IsReady()
void ParticleEmitter::SetParticleCount(uint32_t maxParticleCount)
{
- // Default particle list has no data streams, it will replace old list
- mParticleList = ParticleSystem::ParticleList::New(maxParticleCount,
- ParticleStream::POSITION_STREAM_BIT |
- ParticleStream::COLOR_STREAM_BIT |
- ParticleStream::VELOCITY_STREAM_BIT |
- ParticleStream::SCALE_STREAM_BIT |
- ParticleStream::LIFETIME_STREAM_BIT);
+ if(!mParticleList || maxParticleCount != GetImplementation(mParticleList).GetParticleCount())
+ {
+ // Default particle list has no data streams, it will replace old list
+ mParticleList = ParticleSystem::ParticleList::New(maxParticleCount,
+ ParticleStream::POSITION_STREAM_BIT |
+ ParticleStream::COLOR_STREAM_BIT |
+ ParticleStream::VELOCITY_STREAM_BIT |
+ ParticleStream::SCALE_STREAM_BIT |
+ ParticleStream::LIFETIME_STREAM_BIT);
+ }
+}
+
+uint32_t ParticleEmitter::GetParticleCount()
+{
+ return GetImplementation(mParticleList).GetParticleCount();
}
ParticleSystem::ParticleList& ParticleEmitter::GetParticleList()
void SetParticleCount(uint32_t maxParticleCount);
+ uint32_t GetParticleCount();
+
ParticleSystem::ParticleList& GetParticleList();
uint32_t AddModifier(const ParticleSystem::ParticleModifier& modifier);
mBlendingMode = blendingMode;
}
+BlendingMode ParticleRenderer::GetBlendingMode() const
+{
+ return mBlendingMode;
+}
+
void ParticleRenderer::CreateShader()
{
// Create shader dynamically
void SetBlendingMode(BlendingMode blendingMode);
+ BlendingMode GetBlendingMode() const;
+
bool Initialize();
void PrepareToDie();
#include <dali-toolkit/internal/text/controller/text-controller-impl-model-updater.h>
// EXTERNAL INCLUDES
+#include <chrono>
#include <dali/integration-api/debug.h>
#include <dali/integration-api/trace.h>
#include <dali/public-api/math/math-utils.h>
DALI_INIT_TRACE_FILTER(gTraceFilter, DALI_TRACE_TEXT_PERFORMANCE_MARKER, false);
+#if defined(TRACE_ENABLED)
+uint32_t GetMilliSeconds()
+{
+ // Get the time of a monotonic clock since its epoch.
+ auto epoch = std::chrono::steady_clock::now().time_since_epoch();
+
+ auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(epoch);
+
+ return static_cast<uint32_t>(duration.count());
+}
+#endif
+
// The relative luminance of a color is defined as (L = 0.2126 * R + 0.7152 * G + 0.0722 * B)
// based on W3C Recommendations (https://www.w3.org/TR/WCAG20/)
constexpr float BRIGHTNESS_THRESHOLD = 0.179f;
newParagraphGlyphs.Reserve(numberOfParagraphs);
const Length currentNumberOfGlyphs = glyphs.Count();
+
+#if defined(TRACE_ENABLED)
+ uint32_t logThreshold = TextAbstraction::FontClient::GetPerformanceLogThresholdTime();
+ bool logEnabled = TextAbstraction::FontClient::IsPerformanceLogEnabled();
+
+ uint32_t timeStamps[6];
+ uint32_t timeStampIndex = 0;
+
+ if(logEnabled)
+ {
+ timeStamps[timeStampIndex++] = GetMilliSeconds();
+ }
+#endif
+
if(Controller::NO_OPERATION != (Controller::SHAPE_TEXT & operations))
{
const Vector<Character>& textToShape = textMirrored ? mirroredUtf32Characters : utf32Characters;
updated = true;
}
+#if defined(TRACE_ENABLED)
+ if(logEnabled)
+ {
+ timeStamps[timeStampIndex++] = GetMilliSeconds();
+ }
+#endif
+
const Length numberOfGlyphs = static_cast<Length>(glyphs.Count()) - currentNumberOfGlyphs;
if(Controller::NO_OPERATION != (Controller::GET_GLYPH_METRICS & operations))
updated = true;
}
+#if defined(TRACE_ENABLED)
+ if(logEnabled)
+ {
+ timeStamps[timeStampIndex++] = GetMilliSeconds();
+ }
+#endif
+
if((nullptr != impl.mEventData) &&
impl.mEventData->mPreEditFlag &&
(0u != impl.mModel->mVisualModel->mCharactersToGlyph.Count()))
updated = true;
}
+#if defined(TRACE_ENABLED)
+ if(logEnabled)
+ {
+ timeStamps[timeStampIndex++] = GetMilliSeconds();
+ }
+#endif
+
if(Controller::NO_OPERATION != (Controller::COLOR & operations))
{
// Set the color runs in glyphs.
updated = true;
}
+#if defined(TRACE_ENABLED)
+ if(logEnabled)
+ {
+ timeStamps[timeStampIndex++] = GetMilliSeconds();
+ }
+#endif
+
if((Controller::NO_OPERATION != (Controller::SHAPE_TEXT & operations)) &&
!((nullptr != impl.mEventData) &&
impl.mEventData->mPreEditFlag &&
updated = true;
}
+#if defined(TRACE_ENABLED)
+ if(logEnabled)
+ {
+ timeStamps[timeStampIndex++] = GetMilliSeconds();
+ uint32_t timeShape = timeStamps[1] - timeStamps[0];
+ uint32_t timeGlyph = timeStamps[2] - timeStamps[1];
+ uint32_t timePreedit = timeStamps[3] - timeStamps[2];
+ uint32_t timeColor = timeStamps[4] - timeStamps[3];
+ uint32_t timeCopy = timeStamps[5] - timeStamps[4];
+
+ if(timeStamps[5] - timeStamps[0] > logThreshold)
+ {
+ std::string currentText;
+ Utf32ToUtf8(impl.mModel->mLogicalModel->mText.Begin(), numberOfCharacters, currentText);
+ DALI_LOG_DEBUG_INFO("DALI_TEXT_MODEL_UPDATE shape:%u ms, glyph:%u ms, preedit:%u ms, color:%u ms, copy:%u ms\n", timeShape, timeGlyph, timePreedit, timeColor, timeCopy);
+ DALI_LOG_DEBUG_INFO("DALI_TEXT_MODEL_UPDATE chars:%d, text:%s\n", numberOfCharacters, currentText.c_str());
+ }
+ }
+#endif
+
// The estimated number of lines. Used to avoid reallocations when layouting.
impl.mTextUpdateInfo.mEstimatedNumberOfLines = std::max(impl.mModel->mVisualModel->mLines.Count(), impl.mModel->mLogicalModel->mParagraphInfo.Count());
#include <dali-toolkit/internal/text/shaper.h>
// EXTERNAL INCLUDES
+#include <chrono>
+#include <dali/devel-api/text-abstraction/font-client.h>
#include <dali/devel-api/text-abstraction/shaping.h>
+#include <dali/integration-api/debug.h>
+#include <dali/integration-api/trace.h>
namespace Dali
{
{
namespace Text
{
+DALI_INIT_TRACE_FILTER(gTraceFilter, DALI_TRACE_TEXT_PERFORMANCE_MARKER, false);
+
CharacterIndex min(CharacterIndex index0,
CharacterIndex index1)
{
return (index0 < index1) ? index0 : index1;
}
+#if defined(TRACE_ENABLED)
+uint32_t GetMilliSeconds()
+{
+ // Get the time of a monotonic clock since its epoch.
+ auto epoch = std::chrono::steady_clock::now().time_since_epoch();
+
+ auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(epoch);
+
+ return static_cast<uint32_t>(duration.count());
+}
+#endif
+
void ShapeText(const Vector<Character>& text,
const Vector<LineBreakInfo>& lineBreakInfo,
const Vector<ScriptRun>& scripts,
return;
}
+ DALI_TRACE_SCOPE(gTraceFilter, "DALI_TEXT_SHAPE_TEXT");
+
+#if defined(TRACE_ENABLED)
+ uint32_t sumPre = 0, sumShape = 0, sumPost = 0;
+
+ uint32_t logThreshold = TextAbstraction::FontClient::GetPerformanceLogThresholdTime();
+ bool logEnabled = TextAbstraction::FontClient::IsPerformanceLogEnabled();
+#endif
+
#ifdef DEBUG_ENABLED
const Length numberOfFontRuns = fonts.Count();
const Length numberOfScriptRuns = scripts.Count();
const CharacterIndex lastCharacter = startCharacterIndex + numberOfCharacters;
for(previousIndex = startCharacterIndex; previousIndex < lastCharacter;)
{
+#if defined(TRACE_ENABLED)
+ uint32_t timeStamps[4];
+ uint32_t timeStampIndex = 0;
+
+ if(logEnabled)
+ {
+ timeStamps[timeStampIndex++] = GetMilliSeconds();
+ }
+#endif
+
// Get the font id and the script.
const FontRun& fontRun = *fontRunIt;
const ScriptRun& scriptRun = *scriptRunIt;
}
}
+#if defined(TRACE_ENABLED)
+ if(logEnabled)
+ {
+ timeStamps[timeStampIndex++] = GetMilliSeconds();
+ }
+#endif
+
// Shape the text for the current chunk.
const Length numberOfGlyphs = shaping.Shape(textBuffer + previousIndex,
(currentIndex - previousIndex), // The number of characters to shape.
currentFontId,
currentScript);
+#if defined(TRACE_ENABLED)
+ if(logEnabled)
+ {
+ timeStamps[timeStampIndex++] = GetMilliSeconds();
+ }
+#endif
+
// Retrieve the glyphs and the glyph to character conversion map.
Vector<GlyphInfo> tmpGlyphs;
Vector<CharacterIndex> tmpGlyphToCharacterMap;
// Update the previous index.
previousIndex = currentIndex;
+
+#if defined(TRACE_ENABLED)
+ if(logEnabled)
+ {
+ timeStamps[timeStampIndex++] = GetMilliSeconds();
+ sumPre += timeStamps[1] - timeStamps[0];
+ sumShape += timeStamps[2] - timeStamps[1];
+ sumPost += timeStamps[3] - timeStamps[2];
+ }
+#endif
}
// Update indices.
// Resize the vectors to set the right number of items.
glyphs.Resize(totalNumberOfGlyphs);
glyphToCharacterMap.Resize(totalNumberOfGlyphs);
+
+#if defined(TRACE_ENABLED)
+ if(logEnabled)
+ {
+ if(sumPre + sumShape + sumPost > logThreshold)
+ {
+ DALI_LOG_DEBUG_INFO("DALI_TEXT_SHAPE_TEXT updated:%u/%u, pre:%u ms, shape:%u ms, post:%u ms\n", numberOfNewGlyphs, totalNumberOfGlyphs, sumPre, sumShape, sumPost);
+ }
+ }
+#endif
}
} // namespace Text
// EXTERNAL INCLUDES
#include <dali/integration-api/debug.h>
+#include <dali/integration-api/trace.h>
#include <dali/public-api/math/math-utils.h>
#include <dali/public-api/object/property-array.h>
#include <dali-toolkit/internal/visuals/animated-vector-image/vector-animation-thread.h>
#include <dali-toolkit/internal/visuals/image-visual-shader-factory.h>
+#ifdef TRACE_ENABLED
+#include <sstream>
+#endif
+
namespace Dali
{
namespace Toolkit
Debug::Filter* gVectorAnimationLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_VECTOR_ANIMATION");
#endif
+DALI_INIT_TRACE_FILTER(gTraceFilter, DALI_TRACE_IMAGE_PERFORMANCE_MARKER, false);
+
} // unnamed namespace
VectorAnimationTask::VectorAnimationTask(VisualFactoryCache& factoryCache)
bool VectorAnimationTask::Load(bool synchronousLoading)
{
+ DALI_TRACE_SCOPE(gTraceFilter, "DALI_LOTTIE_LOADING_TASK");
+
if(!mVectorRenderer.Load(mUrl))
{
DALI_LOG_ERROR("VectorAnimationTask::Load: Load failed [%s]\n", mUrl.c_str());
return false;
}
+ DALI_TRACE_BEGIN(gTraceFilter, "DALI_LOTTIE_RASTERIZE_TASK");
+
ApplyAnimationData();
if(mPlayState == PlayState::PLAYING && mUpdateFrameNumber)
mKeepAnimation = true;
}
+#ifdef TRACE_ENABLED
+ if(gTraceFilter && gTraceFilter->IsTraceEnabled())
+ {
+ std::ostringstream oss;
+ oss << "[size: " << mWidth << " x " << mHeight << ", ";
+ oss << "frame: " << mCurrentFrame << ", ";
+ oss << "loop: " << mCurrentLoop << ", ";
+ oss << "state : " << mPlayState << "]";
+ DALI_TRACE_END_WITH_MESSAGE(gTraceFilter, "DALI_LOTTIE_RASTERIZE_TASK", oss.str().c_str());
+ }
+#endif
+
return true;
}
mConditionalWait(),
mNeedToSleep(false),
mDestroyThread(false),
- mLogFactory(Dali::Adaptor::Get().GetLogFactory())
+ mLogFactory(Dali::Adaptor::Get().GetLogFactory()),
+ mTraceFactory(Dali::Adaptor::Get().GetTraceFactory())
{
mAsyncTaskManager = Dali::AsyncTaskManager::Get();
mSleepThread.Start();
{
SetThreadName("VectorAnimationThread");
mLogFactory.InstallLogFunction();
+ mTraceFactory.InstallTraceFunction();
while(!mDestroyThread)
{
mAwakeCallback(std::unique_ptr<CallbackBase>(callback)),
mSleepTimePoint(),
mLogFactory(Dali::Adaptor::Get().GetLogFactory()),
+ mTraceFactory(Dali::Adaptor::Get().GetTraceFactory()),
mNeedToSleep(false),
mDestroyThread(false)
{
{
SetThreadName("VectorSleepThread");
mLogFactory.InstallLogFunction();
+ mTraceFactory.InstallTraceFunction();
while(!mDestroyThread)
{
#include <dali/devel-api/threading/conditional-wait.h>
#include <dali/devel-api/threading/thread.h>
#include <dali/integration-api/adaptor-framework/log-factory-interface.h>
+#include <dali/integration-api/adaptor-framework/trace-factory-interface.h>
#include <dali/public-api/adaptor-framework/round-robin-container-view.h>
#include <dali/public-api/signals/connection-tracker.h>
#include <memory>
std::unique_ptr<CallbackBase> mAwakeCallback;
std::chrono::time_point<std::chrono::steady_clock> mSleepTimePoint;
const Dali::LogFactoryInterface& mLogFactory;
+ const Dali::TraceFactoryInterface& mTraceFactory;
bool mNeedToSleep;
bool mDestroyThread;
};
bool mDestroyThread;
bool mEventTriggered{false};
const Dali::LogFactoryInterface& mLogFactory;
+ const Dali::TraceFactoryInterface& mTraceFactory;
Dali::AsyncTaskManager mAsyncTaskManager;
};
#include <dali/devel-api/scripting/scripting.h>
#include <dali/integration-api/debug.h>
#include <dali/public-api/actors/layer.h>
+#include <dali/public-api/adaptor-framework/async-task-manager.h>
#include <dali/public-api/rendering/decorated-visual-renderer.h>
#include <cstring> // for strlen()
{
RemoveTexture();
}
+
+ ResetFastTrackLoadingTask();
}
}
{
DoSetProperty(Toolkit::ImageVisual::Property::ORIENTATION_CORRECTION, keyValue.second);
}
+ else if(keyValue.first == FAST_TRACK_UPLOADING_NAME)
+ {
+ DoSetProperty(Toolkit::DevelImageVisual::Property::FAST_TRACK_UPLOADING, keyValue.second);
+ }
}
}
// Load image immediately if LOAD_POLICY requires it
}
break;
}
+
+ case Toolkit::DevelImageVisual::Property::FAST_TRACK_UPLOADING:
+ {
+ bool fastTrackUploading = false;
+ if(value.Get(fastTrackUploading))
+ {
+ mUseFastTrackUploading = fastTrackUploading;
+ }
+ break;
+ }
}
}
: TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
bool synchronousLoading = IsSynchronousLoadingRequired();
- bool loadingStatus;
+ bool loadingStatus = false;
+
+ // Remove previous loading task.
+ ResetFastTrackLoadingTask();
+
+ // Rare case. If someone call LoadTexture during fast track loading task running, (Ex : Action::RELOAD)
+ // we should remove previously added renderer now.
+ if(mRendererAdded)
+ {
+ Actor actor = mPlacementActor.GetHandle();
+ if(actor)
+ {
+ actor.RemoveRenderer(mImpl->mRenderer);
+ mRendererAdded = false;
+ }
+ }
+
+ /**
+ * @brief Check whether FastTrackUploading is avaliable or not.
+ * @return True if we can use fast track uploading feature. False otherwise.
+ */
+ auto IsFastTrackUploadingAvailable = [&]() {
+ if(mUseFastTrackUploading &&
+ mLoadPolicy == Toolkit::ImageVisual::LoadPolicy::ATTACHED &&
+ mReleasePolicy == Toolkit::ImageVisual::ReleasePolicy::DETACHED &&
+ forceReload == TextureManager::ReloadPolicy::CACHED &&
+ (mImageUrl.GetProtocolType() == VisualUrl::LOCAL || mImageUrl.GetProtocolType() == VisualUrl::REMOTE) &&
+ !synchronousLoading &&
+ !atlasing &&
+ !mImpl->mCustomShader &&
+ !(mMaskingData && mMaskingData->mAlphaMaskUrl.IsValid()))
+ {
+ return true;
+ }
+ else if(mUseFastTrackUploading)
+ {
+ DALI_LOG_DEBUG_INFO("FastTrack : Fail to load fast track. mUrl : [%s]%s%s%s%s%s%s%s%s\n",
+ mImageUrl.GetUrl().c_str(),
+ (mLoadPolicy != Toolkit::ImageVisual::LoadPolicy::ATTACHED) ? "/ mLoadPolicy != ATTACHED" : "",
+ (mReleasePolicy != Toolkit::ImageVisual::ReleasePolicy::DETACHED) ? "/ mReleasePolicy != DETACHED" : "",
+ (forceReload != TextureManager::ReloadPolicy::CACHED) ? "/ forceReload != CACHED" : "",
+ (!(mImageUrl.GetProtocolType() == VisualUrl::LOCAL || mImageUrl.GetProtocolType() == VisualUrl::REMOTE)) ? "/ url is not image" : "",
+ (synchronousLoading) ? "/ synchronousLoading" : "",
+ (atlasing) ? "/ atlasing" : "",
+ (mImpl->mCustomShader) ? "/ use customs shader" : "",
+ (mMaskingData && mMaskingData->mAlphaMaskUrl.IsValid()) ? "/ use masking url" : "");
+ }
+ return false;
+ };
+
+ if(IsFastTrackUploadingAvailable())
+ {
+ // Enable PremultipliedAlpha first.
+ EnablePreMultipliedAlpha(preMultiplyOnLoad == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD);
+
+ // Set new TextureSet with fast track loading task
+ mFastTrackLoadingTask = new FastTrackLoadingTask(mImageUrl, mDesiredSize, mFittingMode, mSamplingMode, mOrientationCorrection, preMultiplyOnLoad == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD ? DevelAsyncImageLoader::PreMultiplyOnLoad::ON : DevelAsyncImageLoader::PreMultiplyOnLoad::OFF, MakeCallback(this, &ImageVisual::FastLoadComplete));
+
+ TextureSet textureSet = TextureSet::New();
+ textureSet.SetTexture(0u, mFastTrackLoadingTask->mTexture);
+ mImpl->mRenderer.SetTextures(textureSet);
- textures = textureManager.LoadTexture(mImageUrl, mDesiredSize, mFittingMode, mSamplingMode, mMaskingData, synchronousLoading, mTextureId, atlasRect, mAtlasRectSize, atlasing, loadingStatus, textureObserver, atlasUploadObserver, atlasManager, mOrientationCorrection, forceReload, preMultiplyOnLoad);
+ Dali::AsyncTaskManager::Get().AddTask(mFastTrackLoadingTask);
+
+ mLoadState = TextureManager::LoadState::LOADING;
+ }
+ else
+ {
+ textures = textureManager.LoadTexture(mImageUrl, mDesiredSize, mFittingMode, mSamplingMode, mMaskingData, synchronousLoading, mTextureId, atlasRect, mAtlasRectSize, atlasing, loadingStatus, textureObserver, atlasUploadObserver, atlasManager, mOrientationCorrection, forceReload, preMultiplyOnLoad);
+ }
if(textures)
{
if(mLoadState == TextureManager::LoadState::LOAD_FINISHED)
{
actor.AddRenderer(mImpl->mRenderer);
+ mRendererAdded = true;
mPlacementActor.Reset();
// Image loaded and ready to display
ShowBrokenImage();
ResourceReady(Toolkit::Visual::ResourceStatus::FAILED);
}
+ else
+ {
+ if(mFastTrackLoadingTask)
+ {
+ actor.AddRenderer(mImpl->mRenderer);
+ mRendererAdded = true;
+ }
+ }
}
void ImageVisual::DoSetOffScene(Actor& actor)
// Image release is dependent on the ReleasePolicy, renderer is removed.
actor.RemoveRenderer(mImpl->mRenderer);
+ mRendererAdded = false;
+
if(mReleasePolicy == Toolkit::ImageVisual::ReleasePolicy::DETACHED)
{
ResetRenderer();
map.Insert(Toolkit::ImageVisual::Property::LOAD_POLICY, mLoadPolicy);
map.Insert(Toolkit::ImageVisual::Property::RELEASE_POLICY, mReleasePolicy);
map.Insert(Toolkit::ImageVisual::Property::ORIENTATION_CORRECTION, mOrientationCorrection);
+
+ map.Insert(Toolkit::DevelImageVisual::Property::FAST_TRACK_UPLOADING, mUseFastTrackUploading);
}
void ImageVisual::DoCreateInstancePropertyMap(Property::Map& map) const
{
mImpl->mRenderer.RegisterProperty(ATLAS_RECT_UNIFORM_NAME, mAtlasRect);
actor.AddRenderer(mImpl->mRenderer);
+ mRendererAdded = true;
// reset the weak handle so that the renderer only get added to actor once
mPlacementActor.Reset();
}
mLoadState = TextureManager::LoadState::LOAD_FINISHED;
}
+// From FastTrackLoadingTask
+void ImageVisual::FastLoadComplete(FastTrackLoadingTaskPtr task)
+{
+ Toolkit::Visual::ResourceStatus resourceStatus;
+
+ DALI_ASSERT_ALWAYS(mFastTrackLoadingTask == task && "Task was not canceled successfully!");
+ DALI_ASSERT_ALWAYS(mRendererAdded && "Some FastTrack logic missed!");
+
+ Actor actor = mPlacementActor.GetHandle();
+
+ if(mFastTrackLoadingTask && mFastTrackLoadingTask->mLoadSuccess)
+ {
+ resourceStatus = Toolkit::Visual::ResourceStatus::READY;
+ mLoadState = TextureManager::LoadState::LOAD_FINISHED;
+
+ // Change premultiplied alpha flag after change renderer.
+ EnablePreMultipliedAlpha(mFastTrackLoadingTask->mPremultiplied);
+ }
+ else
+ {
+ resourceStatus = Toolkit::Visual::ResourceStatus::FAILED;
+ mLoadState = TextureManager::LoadState::LOAD_FAILED;
+
+ // Change renderer as broken.
+ ShowBrokenImage();
+ }
+
+ mFastTrackLoadingTask.Reset();
+
+ // Signal to observers ( control ) that resources are ready. Must be all resources.
+ ResourceReady(resourceStatus);
+}
+
// From Texture Manager
void ImageVisual::LoadComplete(bool loadingSuccess, TextureInformation textureInformation)
{
if(actor)
{
actor.AddRenderer(mImpl->mRenderer);
+ mRendererAdded = true;
// reset the weak handle so that the renderer only get added to actor once
mPlacementActor.Reset();
}
}
else
{
+ ResetFastTrackLoadingTask();
+
Vector4 atlasRect(0.f, 0.f, 1.f, 1.f);
Property::Index index = mImpl->mRenderer.GetPropertyIndex(ATLAS_RECT_UNIFORM_NAME);
if(index != Property::INVALID_INDEX)
{
imageSize = actor.GetProperty(Actor::Property::SIZE).Get<Vector2>();
mPlacementActorSize = imageSize;
+
+ if(mRendererAdded)
+ {
+ actor.RemoveRenderer(mImpl->mRenderer);
+ mRendererAdded = false;
+ }
}
mFactoryCache.UpdateBrokenImageRenderer(mImpl->mRenderer, imageSize);
if(actor)
{
actor.AddRenderer(mImpl->mRenderer);
+ mRendererAdded = true;
mPlacementActor.Reset();
}
}
else
{
+ if(mRendererAdded)
+ {
+ Actor actor = mPlacementActor.GetHandle();
+ if(actor)
+ {
+ actor.RemoveRenderer(mImpl->mRenderer);
+ mRendererAdded = false;
+ }
+ }
ResetRenderer();
}
}
+void ImageVisual::ResetFastTrackLoadingTask()
+{
+ if(mFastTrackLoadingTask)
+ {
+ Dali::AsyncTaskManager::Get().RemoveTask(mFastTrackLoadingTask);
+ mFastTrackLoadingTask.Reset();
+ }
+}
+
} // namespace Internal
} // namespace Toolkit
#include <dali/public-api/common/intrusive-ptr.h>
#include <dali/public-api/images/image-operations.h>
#include <dali/public-api/object/weak-handle.h>
+#include <dali/public-api/rendering/visual-renderer.h>
// INTERNAL INCLUDES
#include <dali-toolkit/devel-api/image-loader/atlas-upload-observer.h>
#include <dali-toolkit/devel-api/visuals/image-visual-properties-devel.h>
+#include <dali-toolkit/internal/image-loader/fast-track-loading-task.h>
#include <dali-toolkit/internal/texture-manager/texture-upload-observer.h>
#include <dali-toolkit/internal/visuals/visual-base-impl.h>
#include <dali-toolkit/internal/visuals/visual-url.h>
*/
void LoadComplete(bool success, TextureInformation textureInformation) override;
+ /**
+ * @brief Test callback for FastTrackLoadingTask
+ *
+ * @param[in] task The pointer of task who call this callback.
+ */
+ void FastLoadComplete(FastTrackLoadingTaskPtr task);
+
private:
/**
* Allocate the mask data when a masking property is defined in the property map
*/
void ShowBrokenImage();
+ /**
+ * @brief Remove current added fast track upload task.
+ */
+ void ResetFastTrackLoadingTask();
+
private:
Vector4 mPixelArea;
WeakHandle<Actor> mPlacementActor;
Vector2 mTextureSize;
Vector2 mPlacementActorSize;
+ FastTrackLoadingTaskPtr mFastTrackLoadingTask; ///< For fast track uploading.
+
ImageVisualShaderFactory& mImageVisualShaderFactory;
Dali::FittingMode::Type mFittingMode : 3;
Dali::Toolkit::ImageVisual::ReleasePolicy::Type mReleasePolicy;
Vector4 mAtlasRect;
Dali::ImageDimensions mAtlasRectSize;
- TextureManager::LoadState mLoadState; ///< The texture loading state
- bool mAttemptAtlasing; ///< If true will attempt atlasing, otherwise create unique texture
- bool mOrientationCorrection; ///< true if the image will have it's orientation corrected.
- bool mNeedYuvToRgb{false}; ///< true if we need to convert yuv to rgb.
- bool mEnableBrokenImage;
+ TextureManager::LoadState mLoadState; ///< The texture loading state
+ bool mAttemptAtlasing; ///< If true will attempt atlasing, otherwise create unique texture
+ bool mOrientationCorrection; ///< true if the image will have it's orientation corrected.
+ bool mNeedYuvToRgb{false}; ///< true if we need to convert yuv to rgb.
+ bool mEnableBrokenImage{true}; ///< true if enable broken image.
+ bool mUseFastTrackUploading{false}; ///< True if we use fast tack feature.
+ bool mRendererAdded{false}; ///< True if renderer added into actor.
};
} // namespace Internal
TextureManager& textureManager = mFactoryCache.GetTextureManager();
bool synchronousLoading = mImpl->mFlags & Impl::IS_SYNCHRONOUS_RESOURCE_LOADING;
- if(mId == NPatchData::INVALID_NPATCH_DATA_ID && (mImageUrl.IsLocalResource() || mImageUrl.IsBufferResource()))
+ if(mId == NPatchData::INVALID_NPATCH_DATA_ID)
{
bool preMultiplyOnLoad = IsPreMultipliedAlphaEnabled() && !mImpl->mCustomShader ? true : false;
mId = mLoader.Load(textureManager, this, mImageUrl, mBorder, preMultiplyOnLoad, synchronousLoading);
}
}
- if(mAuxiliaryTextureId == TextureManager::INVALID_TEXTURE_ID && mAuxiliaryUrl.IsValid() && (mAuxiliaryUrl.IsLocalResource() || mAuxiliaryUrl.IsBufferResource()))
+ if(mAuxiliaryTextureId == TextureManager::INVALID_TEXTURE_ID && mAuxiliaryUrl.IsValid())
{
auto preMultiplyOnLoad = IsPreMultipliedAlphaEnabled() && !mImpl->mCustomShader
? TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD
#include <dali/devel-api/adaptor-framework/file-loader.h>
#include <dali/integration-api/adaptor-framework/adaptor.h>
#include <dali/integration-api/debug.h>
+#include <dali/integration-api/trace.h>
// INTERNAL INCLUDES
#include <dali-toolkit/internal/visuals/svg/svg-visual.h>
+#ifdef TRACE_ENABLED
+#include <sstream>
+#endif
+
namespace Dali
{
namespace Toolkit
{
namespace Internal
{
+namespace
+{
+DALI_INIT_TRACE_FILTER(gTraceFilter, DALI_TRACE_IMAGE_PERFORMANCE_MARKER, false);
+}
+
SvgTask::SvgTask(VectorImageRenderer vectorRenderer, CallbackBase* callback, AsyncTask::PriorityType priorityType)
: AsyncTask(callback, priorityType),
mVectorRenderer(vectorRenderer),
return;
}
+ DALI_TRACE_SCOPE(gTraceFilter, "DALI_SVG_LOADING_TASK");
+
Dali::Vector<uint8_t> buffer;
if(!mUrl.IsLocalResource())
return;
}
+#ifdef TRACE_ENABLED
+ if(gTraceFilter && gTraceFilter->IsTraceEnabled())
+ {
+ std::ostringstream oss;
+ oss << "[size: " << mWidth << " x " << mHeight << "]";
+ DALI_TRACE_BEGIN_WITH_MESSAGE(gTraceFilter, "DALI_SVG_RASTERIZE_TASK", oss.str().c_str());
+ }
+#endif
+
Devel::PixelBuffer pixelBuffer = mVectorRenderer.Rasterize(mWidth, mHeight);
if(!pixelBuffer)
{
DALI_LOG_ERROR("Rasterize is failed!\n");
+ DALI_TRACE_END(gTraceFilter, "DALI_SVG_RASTERIZE_TASK");
return;
}
mPixelData = Devel::PixelBuffer::Convert(pixelBuffer);
mHasSucceeded = true;
+ DALI_TRACE_END(gTraceFilter, "DALI_SVG_RASTERIZE_TASK");
}
bool SvgRasterizingTask::IsReady()
void SvgVisual::DoSetOffScene(Actor& actor)
{
- // Remove loading & rasterizing task
- if(mLoadingTask)
- {
- Dali::AsyncTaskManager::Get().RemoveTask(mLoadingTask);
- mLoadingTask.Reset();
- }
+ // Remove rasterizing task
if(mRasterizingTask)
{
Dali::AsyncTaskManager::Get().RemoveTask(mRasterizingTask);
const char* const REDRAW_IN_SCALING_DOWN_NAME("redrawInScalingDown");
const char* const MASKING_TYPE_NAME("maskingType");
const char* const MASK_TEXTURE_RATIO_NAME("maskTextureRatio");
+const char* const FAST_TRACK_UPLOADING_NAME("fastTrackUploading");
const char* const ENABLE_BROKEN_IMAGE("enableBrokenImage");
// Text visual
extern const char* const REDRAW_IN_SCALING_DOWN_NAME;
extern const char* const MASKING_TYPE_NAME;
extern const char* const MASK_TEXTURE_RATIO_NAME;
+extern const char* const FAST_TRACK_UPLOADING_NAME;
extern const char* const ENABLE_BROKEN_IMAGE;
// Text visual
{
const unsigned int TOOLKIT_MAJOR_VERSION = 2;
const unsigned int TOOLKIT_MINOR_VERSION = 2;
-const unsigned int TOOLKIT_MICRO_VERSION = 38;
+const unsigned int TOOLKIT_MICRO_VERSION = 39;
const char* const TOOLKIT_BUILD_DATE = __DATE__ " " __TIME__;
#ifdef DEBUG_ENABLED
GetImplementation(*this).SetParticleCount(maxParticleCount);
}
+uint32_t ParticleEmitter::GetParticleCount()
+{
+ return GetImplementation(*this).GetParticleCount();
+}
+
ParticleDomain ParticleEmitter::GetDomain() const
{
return GetImplementation(*this).GetDomain();
void SetParticleCount(uint32_t maxParticleCount);
/**
+ * @brief Returns maximum number of particles in the system
+ *
+ * @return Maximum number of particles
+ */
+ uint32_t GetParticleCount();
+
+ /**
* @brief Returns currently used particle emitter domain
*
* @return Handle to the ParticleDomain object
*/
[[nodiscard]] ParticleRenderer GetRenderer() const;
-
/**
* @brief Attaches particle system to an actor
*
return GetImplementation(*this).GetStreamElementSize(includeLocalStreams);
}
+int ParticleList::GetDefaultStreamIndex(ParticleStreamTypeFlagBit defaultStreamBit)
+{
+ return GetImplementation(*this).GetDefaultStreamIndex(defaultStreamBit);
+}
+
std::list<Particle>& ParticleList::GetActiveParticles()
{
return GetImplementation(*this).GetParticles();
ParticleList::ParticleList() = default;
-
} // namespace Dali::Toolkit::ParticleSystem
\ No newline at end of file
#include <dali-toolkit/public-api/particle-system/particle.h>
// EXTERNAL INCLUDES
-#include <dali/public-api/object/base-handle.h>
#include <dali/public-api/common/list-wrapper.h>
+#include <dali/public-api/object/base-handle.h>
#include <cinttypes>
-
namespace Dali::Toolkit::ParticleSystem::Internal
{
class ParticleList;
*/
uint32_t GetParticleDataSize(bool includeLocalStreams);
+ /**
+ * @brief Returns index associated with specified default stream
+ *
+ * @param[in] defaultStreamBit Default stream bit
+ * @return Returns a valid index or -1 on error.
+ */
+ int GetDefaultStreamIndex(ParticleStreamTypeFlagBit defaultStreamBit);
+
std::list<Particle>& GetActiveParticles();
private:
return {dynamic_cast<Internal::ParticleModifier*>(handle.GetObjectPtr())};
}
+ParticleModifierInterface& ParticleModifier::GetModifierCallback()
+{
+ return GetImplementation(*this).GetUpdater();
+}
+
} // namespace Dali::Toolkit::ParticleSystem
\ No newline at end of file
{
return New(std::move(std::make_unique<T>(args...)));
}
+ /**
+ * @brief Returns associated particle modifier callback
+ *
+ * @return Valid reference to associated callback
+ */
+ ParticleModifierInterface& GetModifierCallback();
/**
* @brief Downcasts a handle to ParticleModifier handle.
GetImplementation(*this).SetBlendingMode(blendingMode);
}
+BlendingMode ParticleRenderer::GetBlendingMode() const
+{
+ return GetImplementation(*this).GetBlendingMode();
+}
+
ParticleRenderer ParticleRenderer::DownCast(BaseHandle handle)
{
return {dynamic_cast<Internal::ParticleRenderer*>(handle.GetObjectPtr())};
void SetBlendingMode(BlendingMode blendingMode);
/**
+ * @brief Sets blending mode for the renderer
+ *
+ * @return Current blending mode
+ */
+ BlendingMode GetBlendingMode() const;
+
+ /**
* @brief Sets renderable as a 2D texture (sprites)
*
* @param[in] texture Valid texture
Name: dali2-toolkit
Summary: Dali 3D engine Toolkit
-Version: 2.2.38
+Version: 2.2.39
Release: 1
Group: System/Libraries
License: Apache-2.0 and BSD-3-Clause and MIT