build
build.log
tct*core.h
-CMakeLists.txt
+/CMakeLists.txt
results_xml.*
--- /dev/null
+SET(PKG_NAME "dali-shader-generator")
+
+SET(EXEC_NAME "tct-${PKG_NAME}-core")
+
+PKG_CHECK_MODULES(${EXEC_NAME} REQUIRED
+ dali2-toolkit
+)
+
+ADD_EXECUTABLE(${EXEC_NAME} ${EXEC_NAME}.cpp)
+
+INSTALL(PROGRAMS ${EXEC_NAME}
+ DESTINATION ${BIN_DIR}/${EXEC_NAME}
+)
+
+SET(SHADER_GENERATOR dali-shader-generator)
+SET(GENERATED_FOLDER ${CMAKE_CURRENT_BINARY_DIR}/shader/generated)
+SET(SHADER_FOLDER ${CMAKE_CURRENT_SOURCE_DIR}/shader)
+
+ADD_CUSTOM_TARGET(test_help ALL COMMAND ${SHADER_GENERATOR} -h | grep "DALi Shader Generator" > /dev/null 2>&1 && echo "test_help Succeeded" VERBATIM)
+ADD_CUSTOM_TARGET(test_no_params ALL COMMAND ${SHADER_GENERATOR} > /dev/null 2>&1 || echo "test_no_params Succeeded" VERBATIM)
+ADD_CUSTOM_TARGET(test_version ALL COMMAND ${SHADER_GENERATOR} -v | wc -l | grep 1 > /dev/null 2>&1 && echo "test_version Succeeded" VERBATIM)
+ADD_CUSTOM_TARGET(test_invalid_option ALL COMMAND ${SHADER_GENERATOR} --undeclared > /dev/null 2>&1 || echo "test_invalid_option Succeeded" VERBATIM)
+ADD_CUSTOM_TARGET(test_too_many_params ALL COMMAND ${SHADER_GENERATOR} ONE TWO THREE > /dev/null 2>&1 || echo "test_too_many_params Succeeded" VERBATIM)
+ADD_CUSTOM_TARGET(test_invalid_indir ALL COMMAND ${SHADER_GENERATOR} ONE TWO > /dev/null 2>&1 || echo "test_invalid_indir Succeeded" VERBATIM)
+ADD_CUSTOM_TARGET(
+ test_check_built_in_created
+ ALL
+ COMMAND ${SHADER_GENERATOR} . ${GENERATED_FOLDER} | grep builtin-shader | wc -l | grep 2 > /dev/null 2>&1 && echo "test_check_built_in_created Succeeded"
+ VERBATIM)
+ADD_CUSTOM_TARGET(
+ test_check_built_in_not_created
+ ALL
+ COMMAND ${SHADER_GENERATOR} --skip . ${GENERATED_FOLDER} | grep builtin-shader > /dev/null 2>&1 || echo "test_check_built_in_not_created Succeeded"
+ VERBATIM)
+ADD_CUSTOM_TARGET(
+ test_frag_correct
+ ALL
+ COMMAND ${SHADER_GENERATOR} ${SHADER_FOLDER} ${GENERATED_FOLDER} | grep "SHADER_FRAGMENT_SHADER_FRAG" | grep "fragment-shader-frag.h" > /dev/null 2>&1 && echo "test_frag_correct Succeeded"
+ VERBATIM)
+ADD_CUSTOM_TARGET(
+ test_vert_correct
+ ALL
+ COMMAND ${SHADER_GENERATOR} ${SHADER_FOLDER} ${GENERATED_FOLDER} | grep "SHADER_VERTEX_SHADER_VERT" | grep "vertex-shader-vert.h" > /dev/null 2>&1 && echo "test_vert_correct Succeeded"
+ VERBATIM)
+ADD_CUSTOM_TARGET(
+ test_def_correct
+ ALL
+ COMMAND ${SHADER_GENERATOR} ${SHADER_FOLDER} ${GENERATED_FOLDER} | grep "SHADER_SHADER_DEFINE_DEF" | grep "shader-define-def.h" > /dev/null 2>&1 && echo "test_def_correct Succeeded"
+ VERBATIM)
--- /dev/null
+varying mediump vec2 vTexCoord;
+
+uniform sampler2D sTexture;
+uniform lowp vec4 uColor;
+
+void main()
+{
+ mediump vec4 color = texture2D( sTexture, vTexCoord );
+ if(color.a <= 0.0001)
+ {
+ discard;
+ }
+ gl_FragColor = color * uColor;
+}
--- /dev/null
+#version 300 es
+precision highp float;
--- /dev/null
+attribute mediump vec2 aPosition;
+uniform highp mat4 uMvpMatrix;
+uniform highp vec3 uSize;
+
+uniform mediump vec2 start_point;
+uniform mediump vec2 end_point;
+uniform mediump vec2 rotate_center;
+uniform mediump float rotate_angle;
+
+varying mediump vec2 vTexCoord;
+varying mediump vec2 vStart;
+varying mediump vec2 vEnd;
+
+vec2 rotate(vec2 x, vec2 c, float a)
+{
+ vec2 d = x - c;
+ vec2 r = vec2(d.x * cos(a) - d.y * sin(a), d.x * sin(a) + d.y * cos(a));
+
+#ifdef UNIT_TYPE_BOUNDING_BOX
+ return r + c;
+#endif
+
+ /* UnitType::OBJECT_BOUNDING_BOX */
+#ifdef UNIT_TYPE_USER
+ return (r + c) / uSize.x;
+#endif
+ /* UnitType::USER_SPACE*/
+}
+
+//Visual size and offset
+uniform mediump vec2 offset;
+uniform highp vec2 size;
+uniform mediump vec4 offsetSizeMode;
+uniform mediump vec2 origin;
+uniform mediump vec2 anchorPoint;
+
+vec4 ComputeVertexPosition()
+{
+ vec2 visualSize = mix( uSize.xy*size, size, offsetSizeMode.zw );
+ vec2 visualOffset = mix( offset, offset/uSize.xy, offsetSizeMode.xy );
+ return vec4( (aPosition + anchorPoint)*visualSize + (visualOffset + origin)*uSize.xy, 0.0, 1.0 );
+}
+
+void main()
+{
+ vStart = rotate( start_point, rotate_center, rotate_angle );
+ vEnd = rotate( end_point, rotate_center, rotate_angle );
+ gl_Position = uMvpMatrix * ComputeVertexPosition();
+
+#ifdef UNIT_TYPE_BOUNDING_BOX
+ vTexCoord = vec2(aPosition.x, -aPosition.y);
+#endif
+/* UnitType::OBJECT_BOUNDING_BOX */
+
+#ifdef UNIT_TYPE_USER
+ vTexCoord = vec2(aPosition.x, -aPosition.y * uSize.y / uSize.x);
+#endif
+/* UnitType::USER_SPACE*/
+}
--- /dev/null
+#include <iostream>
+int main(int argc, char * const argv[])
+{
+ std::cout << "All tests run as part of Cmake build." << std::endl;
+ return 0;
+}
#define DALI_TOOLKIT_ADAPTOR_IMPL_H
/*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 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.
void AddWindow( Internal::Adaptor::SceneHolder* window );
void RemoveWindow( Internal::Adaptor::SceneHolder* window );
- void RegisterProcessor( Integration::Processor& processor );
- void UnregisterProcessor( Integration::Processor& processor );
+ void RegisterProcessor( Integration::Processor& processor, bool postProcessor = false);
+ void UnregisterProcessor( Integration::Processor& processor, bool postProcessor = false);
void SetApplication( Dali::TestApplication& testApplication );
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 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.
}
}
-void Adaptor::RegisterProcessor( Integration::Processor& processor )
+void Adaptor::RegisterProcessor( Integration::Processor& processor, bool postProcessor )
{
Integration::Core& core = mTestApplication->GetCore();
- core.RegisterProcessor( processor );
+ core.RegisterProcessor( processor, postProcessor );
}
-void Adaptor::UnregisterProcessor( Integration::Processor& processor )
+void Adaptor::UnregisterProcessor( Integration::Processor& processor, bool postProcessor )
{
Integration::Core& core = mTestApplication->GetCore();
- core.UnregisterProcessor( processor );
+ core.UnregisterProcessor( processor, postProcessor );
}
void Adaptor::SetApplication( Dali::TestApplication& testApplication )
return *gLogFactory;
}
-void Adaptor::RegisterProcessor( Integration::Processor& processor )
+void Adaptor::RegisterProcessor( Integration::Processor& processor, bool postProcessor)
{
- mImpl->RegisterProcessor( processor );
+ mImpl->RegisterProcessor( processor, postProcessor );
}
-void Adaptor::UnregisterProcessor( Integration::Processor& processor )
+void Adaptor::UnregisterProcessor( Integration::Processor& processor, bool postProcessor)
{
- mImpl->UnregisterProcessor( processor );
+ mImpl->UnregisterProcessor( processor, postProcessor );
}
} // namespace Dali
/*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 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 <toolkit-vector-animation-renderer.h>
#include <toolkit-event-thread-callback.h>
#include <memory>
+#include <thread>
+#include <chrono>
namespace Dali
{
namespace Adaptor
{
+namespace
+{
+Dali::Internal::Adaptor::VectorAnimationRenderer* gVectorAnimationRenderer = nullptr;
+}
+
class VectorAnimationRenderer: public Dali::BaseObject
{
public:
mRenderer(),
mWidth( 0 ),
mHeight( 0 ),
+ mTotalFrameNumber(VECTOR_ANIMATION_TOTAL_FRAME_NUMBER),
mPreviousFrame( 0 ),
+ mDelayTime(0),
+ mDroppedFrames(0),
mFrameRate( 60.0f ),
+ mNeedDroppedFrames(false),
mEventThreadCallback( new EventThreadCallback( MakeCallback( this, &VectorAnimationRenderer::OnTriggered ) ) )
{
mCount++;
{
return false;
}
+ else if(mUrl == "framedrop.json")
+ {
+ // Change total frame number for test
+ mTotalFrameNumber = 200;
+ }
return true;
}
bool Render( uint32_t frameNumber )
{
+ if(mDelayTime != 0)
+ {
+ std::this_thread::sleep_for(std::chrono::milliseconds(static_cast<int32_t>(mDelayTime)));
+ mDelayTime = 0;
+ mNeedDroppedFrames = true;
+ }
+ else if(mNeedDroppedFrames)
+ {
+ mDroppedFrames = (frameNumber > mPreviousFrame) ? frameNumber - mPreviousFrame - 1: frameNumber + (mTotalFrameNumber - mPreviousFrame) - 1;
+ mNeedTrigger = true;
+ mNeedDroppedFrames = false;
+ }
+
if( mNeedTrigger )
{
mEventThreadCallback->Trigger();
uint32_t GetTotalFrameNumber() const
{
- return VECTOR_ANIMATION_TOTAL_FRAME_NUMBER;
+ return mTotalFrameNumber;
}
float GetFrameRate() const
Dali::Renderer mRenderer;
uint32_t mWidth;
uint32_t mHeight;
+ uint32_t mTotalFrameNumber;
uint32_t mPreviousFrame;
+ uint32_t mDelayTime;
+ uint32_t mDroppedFrames;
float mFrameRate;
+ bool mNeedDroppedFrames;
Dali::VectorAnimationRenderer::UploadCompletedSignalType mUploadCompletedSignal;
std::unique_ptr< EventThreadCallback > mEventThreadCallback;
};
{
Internal::Adaptor::VectorAnimationRenderer* animationRenderer = new Internal::Adaptor::VectorAnimationRenderer();
+ Internal::Adaptor::gVectorAnimationRenderer = animationRenderer;
+
return VectorAnimationRenderer( animationRenderer );
}
Dali::Internal::Adaptor::VectorAnimationRenderer::mNeedTrigger = true;
}
+void DelayRendering(uint32_t delay)
+{
+ Dali::Internal::Adaptor::gVectorAnimationRenderer->mDelayTime = delay;
+}
+
+uint32_t GetDroppedFrames()
+{
+ return Dali::Internal::Adaptor::gVectorAnimationRenderer->mDroppedFrames;
+}
+
} // VectorAnimationRenderer
} // Test
#define DALI_TOOLKIT_TEST_VECTOR_ANIMATION_RENDERER_H
/*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 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.
#define VECTOR_ANIMATION_MARKER_END_FRAME_2 3
void RequestTrigger();
+void DelayRendering(uint32_t delay);
+uint32_t GetDroppedFrames();
} // VectorAnimationRenderer
} // Test
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 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.
{
const char* TEST_VECTOR_IMAGE_FILE_NAME = TEST_RESOURCE_DIR "/insta_camera.json";
+const char* TEST_VECTOR_IMAGE_FILE_NAME_FRAME_DROP = "framedrop.json";
const char* TEST_VECTOR_IMAGE_INVALID_FILE_NAME = "invalid.json";
bool gAnimationFinishedSignalFired = false;
END_TEST;
}
+
+int UtcDaliAnimatedVectorImageVisualFrameDrops(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline("UtcDaliAnimatedVectorImageVisualFrameDrops");
+
+ Property::Map propertyMap;
+ propertyMap.Add(Toolkit::Visual::Property::TYPE, DevelVisual::ANIMATED_VECTOR_IMAGE)
+ .Add(ImageVisual::Property::URL, TEST_VECTOR_IMAGE_FILE_NAME_FRAME_DROP);
+
+ Visual::Base visual = VisualFactory::Get().CreateVisual(propertyMap);
+ DALI_TEST_CHECK(visual);
+
+ DummyControl actor = DummyControl::New(true);
+ DummyControlImpl& dummyImpl = static_cast<DummyControlImpl&>(actor.GetImplementation());
+ dummyImpl.RegisterVisual(DummyControl::Property::TEST_VISUAL, visual);
+
+ Vector2 controlSize(20.f, 30.f);
+ actor.SetProperty(Actor::Property::SIZE, controlSize);
+
+ application.GetScene().Add(actor);
+
+ application.SendNotification();
+ application.Render();
+
+ Property::Map attributes;
+ DevelControl::DoAction(actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::PLAY, attributes);
+
+ application.SendNotification();
+ application.Render();
+
+ // Trigger count is 1 - render the first frame
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+
+ // Make delay to drop frames
+ Test::VectorAnimationRenderer::DelayRendering(170); // longer than 16.6 * 10frames
+
+ // Check dropped frame
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+
+ uint32_t frames = Test::VectorAnimationRenderer::GetDroppedFrames();
+ DALI_TEST_CHECK(frames >= 9);
+
+ END_TEST;
+}
END_TEST;
}
+
+
+int utcDaliTextEditorGetHeightForWidthDoesNotChangeLineCountScrollingCase(void)
+{
+ ToolkitTestApplication application;
+
+ tet_infoline(" utcDaliTextEditorGetHeightForWidthDoesNotChangeLineCountScrollingCase ");
+
+ int lineCountBefore =0 ;
+ int lineCountAfter =0 ;
+
+ // Create a text editor
+ TextEditor textEditor = TextEditor::New();
+ //Set very large font-size using point-size
+ textEditor.SetProperty( TextEditor::Property::POINT_SIZE, 10) ;
+ //Specify font-family
+ textEditor.SetProperty( TextEditor::Property::FONT_FAMILY, "DejaVu Sans");
+ //Specify size
+ textEditor.SetProperty( Actor::Property::SIZE, Vector2( 100.f, 100.f ) );
+ //Set text longer than width of textEditor
+ textEditor.SetProperty( TextEditor::Property::TEXT, "TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST ");
+
+ application.GetScene().Add( textEditor );
+
+ application.SendNotification();
+ application.Render();
+
+ //Failed case is the GetHeightForWidth change LineCount then the scrollor will not arrive to latest line
+ //GetHeightForWidth is a retrieval method which should not modify object
+ lineCountBefore = textEditor.GetProperty<int>( TextEditor::Property::LINE_COUNT );
+ textEditor.GetHeightForWidth(200.f);
+
+ //This is to simulate focus into text editor after calling GetHeightForWidth
+ //Create a tap event to touch the text editor.
+ TestGenerateTap( application, 18.0f, 25.0f );
+
+ application.SendNotification();
+ application.Render();
+
+ lineCountAfter = textEditor.GetProperty<int>( TextEditor::Property::LINE_COUNT );
+
+ //The LineCount must not be changed when calling GetHeightForWidth.
+ DALI_TEST_EQUALS( lineCountAfter , lineCountBefore, TEST_LOCATION );
+
+ END_TEST;
+}
+
+int utcDaliTextEditorGetHeightForWidthDoesNotChangeLineCountLineWrapCharCase(void)
+{
+ ToolkitTestApplication application;
+
+ tet_infoline(" utcDaliTextEditorGetHeightForWidthDoesNotChangeLineCountLineWrapCharCase ");
+
+ int lineCountBefore =0 ;
+ int lineCountAfter =0 ;
+
+ // Create a text editor
+ TextEditor textEditor = TextEditor::New();
+ //Set very large font-size using point-size
+ textEditor.SetProperty( TextEditor::Property::POINT_SIZE, 10) ;
+ //Specify font-family
+ textEditor.SetProperty( TextEditor::Property::FONT_FAMILY, "DejaVu Sans");
+ //Specify size
+ textEditor.SetProperty( Actor::Property::SIZE, Vector2( 50.f, 100.f ) );
+ //Set text longer than width of textEditor
+ textEditor.SetProperty( TextEditor::Property::TEXT, "qwertyuiopasdfghjklzxcvbnm\n");
+ //Set line wrap mode Character
+ textEditor.SetProperty(TextEditor::Property::LINE_WRAP_MODE, "CHARACTER");
+
+ application.GetScene().Add( textEditor );
+
+ application.SendNotification();
+ application.Render();
+
+ //Failed case is the GetHeightForWidth change LineCount which make position of cursor invalid in TextEditor
+ //GetHeightForWidth is a retrieval method which should not modify object
+ lineCountBefore = textEditor.GetProperty<int>( TextEditor::Property::LINE_COUNT );
+ textEditor.GetHeightForWidth(200.f);
+
+ //This is to simulate focus into text editor after calling GetHeightForWidth
+ //Create a tap event to touch the text editor.
+ TestGenerateTap( application, 18.0f, 25.0f );
+
+ application.SendNotification();
+ application.Render();
+
+ lineCountAfter = textEditor.GetProperty<int>( TextEditor::Property::LINE_COUNT );
+
+ //The LineCount must not be changed when calling GetHeightForWidth.
+ DALI_TEST_EQUALS( lineCountAfter , lineCountBefore, TEST_LOCATION );
+
+ END_TEST;
+}
+
+int utcDaliTextEditorGetNaturalSizeDoesNotChangeLineCountScrollingCase(void)
+{
+ ToolkitTestApplication application;
+
+ tet_infoline(" utcDaliTextEditorGetNaturalSizeDoesNotChangeLineCountScrollingCase ");
+
+ int lineCountBefore =0 ;
+ int lineCountAfter =0 ;
+
+ // Create a text editor
+ TextEditor textEditor = TextEditor::New();
+ //Set very large font-size using point-size
+ textEditor.SetProperty( TextEditor::Property::POINT_SIZE, 10) ;
+ //Specify font-family
+ textEditor.SetProperty( TextEditor::Property::FONT_FAMILY, "DejaVu Sans");
+ //Specify size
+ textEditor.SetProperty( Actor::Property::SIZE, Vector2( 100.f, 100.f ) );
+ //Set text longer than width of textEditor
+ textEditor.SetProperty( TextEditor::Property::TEXT, "TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST ");
+
+ application.GetScene().Add( textEditor );
+
+ application.SendNotification();
+ application.Render();
+
+ //Failed case is the GetNaturalSize change LineCount then the scrollor will not arrive to latest line
+ //GetNaturalSize is a retrieval method which should not modify object
+ lineCountBefore = textEditor.GetProperty<int>( TextEditor::Property::LINE_COUNT );
+ textEditor.GetNaturalSize();
+
+ //This is to simulate focus into text editor after calling GetNaturalSize
+ //Create a tap event to touch the text editor.
+ TestGenerateTap( application, 18.0f, 25.0f );
+
+ application.SendNotification();
+ application.Render();
+
+ lineCountAfter = textEditor.GetProperty<int>( TextEditor::Property::LINE_COUNT );
+
+ //The LineCount must not be changed when calling GetNaturalSize.
+ DALI_TEST_EQUALS( lineCountAfter , lineCountBefore, TEST_LOCATION );
+
+ END_TEST;
+}
+
+int utcDaliTextEditorGetNaturalSizeDoesNotChangeLineCountLineWrapCharCase(void)
+{
+ ToolkitTestApplication application;
+
+ tet_infoline(" utcDaliTextEditorGetNaturalSizeDoesNotChangeLineCountLineWrapCharCase ");
+
+ int lineCountBefore =0 ;
+ int lineCountAfter =0 ;
+
+ // Create a text editor
+ TextEditor textEditor = TextEditor::New();
+ //Set very large font-size using point-size
+ textEditor.SetProperty( TextEditor::Property::POINT_SIZE, 10) ;
+ //Specify font-family
+ textEditor.SetProperty( TextEditor::Property::FONT_FAMILY, "DejaVu Sans");
+ //Specify size
+ textEditor.SetProperty( Actor::Property::SIZE, Vector2( 50.f, 100.f ) );
+ //Set text longer than width of textEditor
+ textEditor.SetProperty( TextEditor::Property::TEXT, "qwertyuiopasdfghjklzxcvbnm\n");
+ //Set line wrap mode Character
+ textEditor.SetProperty(TextEditor::Property::LINE_WRAP_MODE, "CHARACTER");
+
+ application.GetScene().Add( textEditor );
+
+ application.SendNotification();
+ application.Render();
+
+ //Failed case is the GetNaturalSize change LineCount which make position of cursor invalid in TextEditor
+ //GetNaturalSize is a retrieval method which should not modify object
+ lineCountBefore = textEditor.GetProperty<int>( TextEditor::Property::LINE_COUNT );
+ textEditor.GetNaturalSize( );
+
+ //This is to simulate focus into text editor after calling GetNaturalSize
+ //Create a tap event to touch the text editor.
+ TestGenerateTap( application, 18.0f, 25.0f );
+
+ application.SendNotification();
+ application.Render();
+
+ lineCountAfter = textEditor.GetProperty<int>( TextEditor::Property::LINE_COUNT );
+
+ //The LineCount must not be changed when calling GetNaturalSize.
+ DALI_TEST_EQUALS( lineCountAfter , lineCountBefore, TEST_LOCATION );
+
+ END_TEST;
+}
\ No newline at end of file
dali.info
*.dylib
dali2-*-config.cmake
-libdali2-scene-loader.so*
\ No newline at end of file
+libdali2-scene-loader.so*
+dali-shader-generator
# Generate source files for shaders
SET(SHADER_SOURCE_DIR "${ROOT_SRC_DIR}/dali-toolkit/internal/graphics/shaders/")
SET(SHADER_GENERATED_DIR "${ROOT_SRC_DIR}/dali-toolkit/internal/graphics/generated")
-EXECUTE_PROCESS( COMMAND bash -c "${CMAKE_CURRENT_SOURCE_DIR}/shader-generator.sh ${SHADER_SOURCE_DIR} ${SHADER_GENERATED_DIR}" )
SET(GENERATED_SHADER_DIR ${ROOT_SRC_DIR}/dali-toolkit/internal/graphics/)
SET_PROPERTY(DIRECTORY PROPERTY ADDITIONAL_MAKE_CLEAN_FILES
"${GENERATED_SHADER_DIR}/generated/"
"${GENERATED_SHADER_DIR}/builtin-shader-extern-gen.h")
+SET(SHADER_GENERATOR_NAME dali-shader-generator)
+SET(SHADER_GENERATOR_SOURCES ${ROOT_SRC_DIR}/dali-toolkit/shader-generator/shader-generator.cpp)
+
+IF(NOT ANDROID)
+ ADD_EXECUTABLE(${SHADER_GENERATOR_NAME} ${SHADER_GENERATOR_SOURCES})
+ INSTALL(TARGETS ${SHADER_GENERATOR_NAME} RUNTIME DESTINATION bin)
+ELSE()
+ # Need to build dali-shader-generator using the host compiler, not the android cross-compiler so
+ # that it can be run on the host machine
+ OPTION(ANDROID_HOST_COMPILER "Provide the host compiler used by Android (Mandatory)")
+ IF(${ANDROID_HOST_COMPILER} STREQUAL "OFF")
+ MESSAGE(FATAL_ERROR "-DANDROID_HOST_COMPILER=\"Compiler\" must be set")
+ ENDIF()
+
+ ADD_CUSTOM_COMMAND(OUTPUT ${SHADER_GENERATOR_NAME}
+ COMMAND ${ANDROID_HOST_COMPILER} -o ${CMAKE_CURRENT_BINARY_DIR}/${SHADER_GENERATOR_NAME} -std=c++17 ${SHADER_GENERATOR_SOURCES})
+ INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${SHADER_GENERATOR_NAME}
+ PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
+ DESTINATION bin)
+ENDIF()
+
+SET(BUILT_IN_SHADER_GEN_CPP "${GENERATED_SHADER_DIR}/generated/builtin-shader-gen.cpp")
+ADD_CUSTOM_COMMAND(OUTPUT ${BUILT_IN_SHADER_GEN_CPP}
+ DEPENDS ${SHADER_GENERATOR_NAME}
+ COMMAND ${CMAKE_CURRENT_BINARY_DIR}/${SHADER_GENERATOR_NAME} ${SHADER_SOURCE_DIR} ${SHADER_GENERATED_DIR})
+
+SET(SOURCES ${SOURCES} ${BUILT_IN_SHADER_GEN_CPP})
+
IF( WIN32 OR APPLE )
SET( DALICORE_LDFLAGS
"${DALICORE_LDFLAGS}"
${prefix_include_dir}
)
+# Generate source files for shaders
+SET(SHADER_SOURCE_DIR "${scene_loader_dir}/internal/graphics/shaders/")
+SET(SHADER_GENERATED_DIR "${scene_loader_dir}/internal/graphics/generated")
+
+SET(GENERATED_SHADER_DIR ${scene_loader_dir}/internal/graphics/)
+SET_PROPERTY(DIRECTORY PROPERTY ADDITIONAL_MAKE_CLEAN_FILES
+ "${GENERATED_SHADER_DIR}/generated/"
+ "${GENERATED_SHADER_DIR}/builtin-shader-extern-gen.h")
+
+SET( BUILT_IN_SHADER_GEN_CPP "${GENERATED_SHADER_DIR}/generated/builtin-shader-gen.cpp")
+ADD_CUSTOM_COMMAND(OUTPUT ${BUILT_IN_SHADER_GEN_CPP}
+ DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/../${SHADER_GENERATOR_NAME}
+ COMMAND ${CMAKE_CURRENT_BINARY_DIR}/../${SHADER_GENERATOR_NAME} ${SHADER_SOURCE_DIR} ${SHADER_GENERATED_DIR})
+
+SET( scene_loader_src_files ${scene_loader_src_files} ${BUILT_IN_SHADER_GEN_CPP} )
+
add_library(${name} SHARED ${scene_loader_src_files})
target_link_libraries(${name} ${DALICORE_LDFLAGS} ${DALIADAPTOR_LDFLAGS}
target_link_libraries(${name} log)
endif()
-# Generate source files for shaders
-SET(SHADER_SOURCE_DIR "${scene_loader_dir}/internal/graphics/shaders/")
-SET(SHADER_GENERATED_DIR "${scene_loader_dir}/internal/graphics/generated")
-EXECUTE_PROCESS( COMMAND bash -c "${repo_root_dir}/build/tizen/shader-generator.sh ${SHADER_SOURCE_DIR} ${SHADER_GENERATED_DIR}" )
-
-SET(GENERATED_SHADER_DIR ${scene_loader_dir}/internal/graphics/)
-SET_PROPERTY(DIRECTORY PROPERTY ADDITIONAL_MAKE_CLEAN_FILES
- "${GENERATED_SHADER_DIR}/generated/"
- "${GENERATED_SHADER_DIR}/builtin-shader-extern-gen.h")
-
IF( INSTALL_CMAKE_MODULES )
SET_TARGET_PROPERTIES( ${name}
PROPERTIES
+++ /dev/null
-#!/bin/bash
-
-indir=$1
-outdir=$2
-
-mkdir -p $outdir
-
-if [ ! -e $indir ] ; then
- echo "Error! "$indir" not found!"
- exit 0
-fi
-
-cd $indir
-all_shaders=$(ls -1 *.{vert,frag,def})
-cd $OLDPWD
-
-# Generate one header file per shader which is defined as a const std::string_view
-for name in $all_shaders ; do
- echo "Generating header files for $name..."
- varname=$(echo "SHADER_$name" | tr [a-z] [A-Z] | sed -e 's/-/_/g;s/\./_/g;')
-
- newname=$(echo ${name} | sed -e 's/\./-/;')".h"
- echo Writing $newname
-
- shader_fullpath=$(echo ${indir})$name
-
- header_name="${varname}_GEN_H"
- echo "const std::string_view" "$varname""{" > $outdir/$newname
- cat $shader_fullpath | sed -e 's/^..*$/"&\\n"/' >> $outdir/$newname
- echo "};" >> $outdir/$newname
-done
-
-# Generate one cpp file that includes all the previously generated string_views for shaders
-echo "Generating cpp file..."
-echo -e "#include \"../builtin-shader-extern-gen.h\"\n" > $outdir/builtin-shader-gen.cpp
-
-varnames=
-for name in $all_shaders ; do
- varname=$(echo "SHADER_$name" | tr [a-z] [A-Z] | sed -e 's/-/_/g;s/\./_/g;')
- newname=$(echo ${name} | sed -e 's/\./-/;')".h"
- varnames="${varnames} $varname"
- echo "#include \"$newname\"" >> $outdir/builtin-shader-gen.cpp
-done
-
-# Generate one header file that defines all the shader string_views as extern variables
-echo "Generating extern header file ( for external use )..."
-echo "#ifndef GRAPHICS_BUILTIN_SHADER_EXTERN_GEN_H" > $outdir/../builtin-shader-extern-gen.h
-echo -e "#define GRAPHICS_BUILTIN_SHADER_EXTERN_GEN_H\n" >> $outdir/../builtin-shader-extern-gen.h
-
-echo "#include <string_view>" >> $outdir/../builtin-shader-extern-gen.h
-echo "" >> $outdir/../builtin-shader-extern-gen.h
-
-for name in $all_shaders ; do
- varname=$(echo "SHADER_$name" | tr [a-z] [A-Z] | sed -e 's/-/_/g;s/\./_/g;')
- newname=$(echo ${name} | sed -e 's/\./-/;')".h"
- echo "extern const std::string_view $varname;" >> $outdir/../builtin-shader-extern-gen.h
-done
-cat >> $outdir/../builtin-shader-extern-gen.h << EOF
-
-#endif // GRAPHICS_BUILTIN_SHADER_EXTERN_GEN_H
-EOF
-
mChanged = true;
}
-void CanvasView::Process()
+void CanvasView::Process(bool postProcessor)
{
if(!mCanvasRenderer)
{
/**
* @copydoc Dali::Integration::Processor::Process()
*/
- void Process() override;
+ void Process(bool postProcessor) override;
private:
/**
${toolkit_src_dir}/transition-effects/cube-transition-wave-effect-impl.cpp
${toolkit_src_dir}/text/xhtml-entities.cpp
${toolkit_src_dir}/drag-drop-detector/drag-and-drop-detector-impl.cpp
- ${toolkit_src_dir}/graphics/generated/builtin-shader-gen.cpp
)
SET( SOURCES ${SOURCES}
{
namespace Text
{
-Vector3 Controller::Relayouter::GetNaturalSize(Controller& controller)
-{
- DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->Controller::GetNaturalSize\n");
- Vector3 naturalSize;
- // Make sure the model is up-to-date before layouting
- controller.ProcessModifyEvents();
+Size Controller::Relayouter::CalculateLayoutSizeOnRequiredControllerSize(Controller& controller, const Size& requestedControllerSize, const OperationsMask& requestedOperationsMask, bool restoreLinesAndGlyphPositions)
+{
+ DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->CalculateLayoutSizeOnRequiredControllerSize\n");
+ Size calculatedLayoutSize;
Controller::Impl& impl = *controller.mImpl;
ModelPtr& model = impl.mModel;
VisualModelPtr& visualModel = model->mVisualModel;
- if(impl.mRecalculateNaturalSize)
+
+ // Store the pending operations mask so that it can be restored later on with no modifications made on it
+ // while getting the natural size were reflected on the original mask.
+ OperationsMask operationsPendingBackUp = static_cast<OperationsMask>(impl.mOperationsPending);
+
+ // This is a hotfix for side effect on Scrolling, LineWrap and Invalid position of cursor in TextEditor after calling CalculateLayoutSizeOnRequiredControllerSize.
+ // The number of lines and glyph-positions inside visualModel have been changed by calling DoRelayout with requestedControllerSize.
+ // Store the mLines and mGlyphPositions from visualModel so that they can be restored later on with no modifications made on them.
+ //TODO: Refactor "DoRelayout" and extract common code of size calculation without modifying attributes of mVisualModel, and then blah, blah, etc.
+ Vector<LineRun> linesBackup = visualModel->mLines;
+ Vector<Vector2> glyphPositionsBackup = visualModel->mGlyphPositions;
+
+ // Operations that can be done only once until the text changes.
+ const OperationsMask onlyOnceOperations = static_cast<OperationsMask>(CONVERT_TO_UTF32 |
+ GET_SCRIPTS |
+ VALIDATE_FONTS |
+ GET_LINE_BREAKS |
+ BIDI_INFO |
+ SHAPE_TEXT |
+ GET_GLYPH_METRICS);
+
+ // Set the update info to relayout the whole text.
+ TextUpdateInfo& textUpdateInfo = impl.mTextUpdateInfo;
+ textUpdateInfo.mParagraphCharacterIndex = 0u;
+ textUpdateInfo.mRequestedNumberOfCharacters = model->mLogicalModel->mText.Count();
+
+ // Make sure the model is up-to-date before layouting
+ impl.UpdateModel(onlyOnceOperations);
+
+ // Get a reference to the pending operations member
+ OperationsMask& operationsPending = impl.mOperationsPending;
+
+ // Layout the text for the new width.
+ operationsPending = static_cast<OperationsMask>(operationsPending | requestedOperationsMask);
+
+ // Store the actual control's size to restore later.
+ const Size actualControlSize = visualModel->mControlSize;
+
+ DoRelayout(controller,
+ requestedControllerSize,
+ static_cast<OperationsMask>(onlyOnceOperations |
+ requestedOperationsMask),
+ calculatedLayoutSize);
+
+
+ // Clear the update info. This info will be set the next time the text is updated.
+ textUpdateInfo.Clear();
+ textUpdateInfo.mClearAll = true;
+
+ // Restore the actual control's size.
+ visualModel->mControlSize = actualControlSize;
+ // Restore the previously backed-up pending operations' mask without the only once operations.
+ impl.mOperationsPending = static_cast<OperationsMask>(operationsPendingBackUp & ~onlyOnceOperations);
+
+ // Restore the previously backed-up mLines and mGlyphPositions from visualModel.
+ if(restoreLinesAndGlyphPositions)
{
- // Store the pending operations mask so that it can be restored later on with no modifications made on it
- // while getting the natural size were reflected on the original mask.
- OperationsMask operationsPendingBackUp = static_cast<OperationsMask>(impl.mOperationsPending);
- // Operations that can be done only once until the text changes.
- const OperationsMask onlyOnceOperations = static_cast<OperationsMask>(CONVERT_TO_UTF32 |
- GET_SCRIPTS |
- VALIDATE_FONTS |
- GET_LINE_BREAKS |
- BIDI_INFO |
- SHAPE_TEXT |
- GET_GLYPH_METRICS);
+ visualModel->mLines = linesBackup;
+ visualModel->mGlyphPositions = glyphPositionsBackup;
+ }
- // Set the update info to relayout the whole text.
- TextUpdateInfo& textUpdateInfo = impl.mTextUpdateInfo;
- textUpdateInfo.mParagraphCharacterIndex = 0u;
- textUpdateInfo.mRequestedNumberOfCharacters = model->mLogicalModel->mText.Count();
+ return calculatedLayoutSize;
+}
- // Make sure the model is up-to-date before layouting
- impl.UpdateModel(onlyOnceOperations);
- // Get a reference to the pending operations member
- OperationsMask& operationsPending = impl.mOperationsPending;
+Vector3 Controller::Relayouter::GetNaturalSize(Controller& controller)
+{
+ DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->Controller::GetNaturalSize\n");
+ Vector3 naturalSizeVec3;
- // Layout the text for the new width.
- operationsPending = static_cast<OperationsMask>(operationsPending | LAYOUT | REORDER);
+ // Make sure the model is up-to-date before layouting
+ controller.ProcessModifyEvents();
+
+ Controller::Impl& impl = *controller.mImpl;
+ ModelPtr& model = impl.mModel;
+ VisualModelPtr& visualModel = model->mVisualModel;
+
+ if(impl.mRecalculateNaturalSize)
+ {
+ Size naturalSize;
- // Store the actual control's size to restore later.
- const Size actualControlSize = visualModel->mControlSize;
+ // Layout the text for the new width.
+ OperationsMask requestedOperationsMask = static_cast<OperationsMask>(LAYOUT | REORDER);
+ Size sizeMaxWidthAndMaxHeight = Size(MAX_FLOAT, MAX_FLOAT);
- DoRelayout(controller,
- Size(MAX_FLOAT, MAX_FLOAT),
- static_cast<OperationsMask>(onlyOnceOperations |
- LAYOUT | REORDER),
- naturalSize.GetVectorXY());
+ naturalSize = CalculateLayoutSizeOnRequiredControllerSize(controller, sizeMaxWidthAndMaxHeight, requestedOperationsMask, true);
// Stores the natural size to avoid recalculate it again
// unless the text/style changes.
- visualModel->SetNaturalSize(naturalSize.GetVectorXY());
+ visualModel->SetNaturalSize(naturalSize);
+ naturalSizeVec3 = naturalSize;
impl.mRecalculateNaturalSize = false;
- // Clear the update info. This info will be set the next time the text is updated.
- textUpdateInfo.Clear();
- textUpdateInfo.mClearAll = true;
-
- // Restore the actual control's size.
- visualModel->mControlSize = actualControlSize;
- // Restore the previously backed-up pending operations' mask without the only once operations.
- impl.mOperationsPending = static_cast<OperationsMask>(operationsPendingBackUp & ~onlyOnceOperations);
- DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::GetNaturalSize calculated %f,%f,%f\n", naturalSize.x, naturalSize.y, naturalSize.z);
+ DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::GetNaturalSize calculated %f,%f,%f\n", naturalSizeVec3.x, naturalSizeVec3.y, naturalSizeVec3.z);
}
else
{
- naturalSize = visualModel->GetNaturalSize();
+ naturalSizeVec3 = visualModel->GetNaturalSize();
- DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::GetNaturalSize cached %f,%f,%f\n", naturalSize.x, naturalSize.y, naturalSize.z);
+ DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::GetNaturalSize cached %f,%f,%f\n", naturalSizeVec3.x, naturalSizeVec3.y, naturalSizeVec3.z);
}
- naturalSize.x = ConvertToEven(naturalSize.x);
- naturalSize.y = ConvertToEven(naturalSize.y);
+ naturalSizeVec3.x = ConvertToEven(naturalSizeVec3.x);
+ naturalSizeVec3.y = ConvertToEven(naturalSizeVec3.y);
- return naturalSize;
+ return naturalSizeVec3;
}
bool Controller::Relayouter::CheckForTextFit(Controller& controller, float pointSize, const Size& layoutSize)
float Controller::Relayouter::GetHeightForWidth(Controller& controller, float width)
{
DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->Controller::GetHeightForWidth %p width %f\n", &controller, width);
+
// Make sure the model is up-to-date before layouting
controller.ProcessModifyEvents();
TextUpdateInfo& textUpdateInfo = impl.mTextUpdateInfo;
Size layoutSize;
+
if(fabsf(width - visualModel->mControlSize.width) > Math::MACHINE_EPSILON_1000 ||
textUpdateInfo.mFullRelayoutNeeded ||
textUpdateInfo.mClearAll)
{
- // Store the pending operations mask so that it can be restored later on with no modifications made on it
- // while getting the natural size were reflected on the original mask.
- OperationsMask operationsPendingBackUp = static_cast<OperationsMask>(impl.mOperationsPending);
- // Operations that can be done only once until the text changes.
- const OperationsMask onlyOnceOperations = static_cast<OperationsMask>(CONVERT_TO_UTF32 |
- GET_SCRIPTS |
- VALIDATE_FONTS |
- GET_LINE_BREAKS |
- BIDI_INFO |
- SHAPE_TEXT |
- GET_GLYPH_METRICS);
-
- // Set the update info to relayout the whole text.
- textUpdateInfo.mParagraphCharacterIndex = 0u;
- textUpdateInfo.mRequestedNumberOfCharacters = model->mLogicalModel->mText.Count();
-
- // Make sure the model is up-to-date before layouting
- impl.UpdateModel(onlyOnceOperations);
-
- // Get a reference to the pending operations member
- OperationsMask& operationsPending = impl.mOperationsPending;
// Layout the text for the new width.
- operationsPending = static_cast<OperationsMask>(operationsPending | LAYOUT);
+ OperationsMask requestedOperationsMask = static_cast<OperationsMask>(LAYOUT);
+ Size sizeRequestedWidthAndMaxHeight = Size(width, MAX_FLOAT);
- // Store the actual control's width.
- const float actualControlWidth = visualModel->mControlSize.width;
+ // Skip restore, because if GetHeightForWidth called before rendering and layouting then visualModel->mControlSize will be zero which will make LineCount zero.
+ // The implementation of Get LineCount property depends on calling GetHeightForWidth then read mLines.Count() from visualModel direct.
+ // If the LineCount property is requested before rendering and layouting then the value will be zero, which is incorrect.
+ // So we will not restore the previously backed-up mLines and mGlyphPositions from visualModel in such case.
+ bool restoreLinesAndGlyphPositions = visualModel->mControlSize.width>0 && visualModel->mControlSize.height>0;
- DoRelayout(controller,
- Size(width, MAX_FLOAT),
- static_cast<OperationsMask>(onlyOnceOperations |
- LAYOUT),
- layoutSize);
-
- // Clear the update info. This info will be set the next time the text is updated.
- textUpdateInfo.Clear();
- textUpdateInfo.mClearAll = true;
+ layoutSize = CalculateLayoutSizeOnRequiredControllerSize(controller, sizeRequestedWidthAndMaxHeight, requestedOperationsMask, restoreLinesAndGlyphPositions);
- // Restore the actual control's width.
- visualModel->mControlSize.width = actualControlWidth;
- // Restore the previously backed-up pending operations' mask without the only once operations.
- impl.mOperationsPending = static_cast<OperationsMask>(operationsPendingBackUp & ~onlyOnceOperations);
DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::GetHeightForWidth calculated %f\n", layoutSize.height);
}
else
* @param[in] controlSize The control size
*/
static void CalculateVerticalOffset(Controller& controller, const Size& controlSize);
+
+ /**
+ * @brief Calculates the layout size of control according to @p requestedControllerSize and @p requestedOperationsMask
+ *
+ * GetNaturalSize() and GetHeightForWidth() calls this method.
+ *
+ * @param[in] controller The controller to calcualte size on it.
+ * @param[in] requestedControllerSize The requested size of controller to calcualte layout size on it.
+ * @param[in] requestedOperationsMask The requested operations-mask to calcualte layout size according to it.
+ * @param[in] restoreLinesAndGlyphPositions whether to restore lines and glyph-positions to status before requesting calculation on size.
+ *
+ * @return The calculated layout-size.
+ */
+ static Size CalculateLayoutSizeOnRequiredControllerSize(Controller& controller, const Size& requestedControllerSize, const OperationsMask& requestedOperationsMask, bool restoreLinesAndGlyphPositions);
+
};
} // namespace Text
}
}
-void VectorAnimationManager::Process()
+void VectorAnimationManager::Process(bool postProcessor)
{
for(auto&& iter : mEventCallbacks)
{
/**
* @copydoc Dali::Integration::Processor::Process()
*/
- void Process() override;
+ void Process(bool postProcessor) override;
private:
// Undefined
namespace
{
constexpr auto LOOP_FOREVER = -1;
-constexpr auto NANOSECONDS_PER_SECOND(1e+9);
+constexpr auto MICROSECONDS_PER_SECOND(1e+6);
#if defined(DEBUG_ENABLED)
Debug::Filter* gVectorAnimationLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_VECTOR_ANIMATION");
mStopBehavior(DevelImageVisual::StopBehavior::CURRENT_FRAME),
mLoopingMode(DevelImageVisual::LoopingMode::RESTART),
mNextFrameStartTime(),
- mFrameDurationNanoSeconds(0),
+ mFrameDurationMicroSeconds(MICROSECONDS_PER_SECOND / 60.0f),
mFrameRate(60.0f),
mCurrentFrame(0),
mTotalFrame(0),
mStartFrame(0),
mEndFrame(0),
+ mDroppedFrames(0),
mWidth(0),
mHeight(0),
mAnimationDataIndex(0),
mEndFrame = mTotalFrame - 1;
- mFrameRate = mVectorRenderer.GetFrameRate();
- mFrameDurationNanoSeconds = NANOSECONDS_PER_SECOND / mFrameRate;
+ mFrameRate = mVectorRenderer.GetFrameRate();
+ mFrameDurationMicroSeconds = MICROSECONDS_PER_SECOND / mFrameRate;
uint32_t width, height;
mVectorRenderer.GetDefaultSize(width, height);
bool VectorAnimationTask::Rasterize()
{
bool stopped = false;
- uint32_t currentFrame;
+ uint32_t currentFrame, droppedFrames = 0;
{
ConditionalWait::ScopedLock lock(mConditionalWait);
// The task will be destroyed. We don't need rasterization.
return false;
}
+ droppedFrames = mDroppedFrames;
}
ApplyAnimationData();
if(mPlayState == PlayState::PLAYING && mUpdateFrameNumber)
{
- mCurrentFrame = mForward ? mCurrentFrame + 1 : mCurrentFrame - 1;
+ mCurrentFrame = mForward ? mCurrentFrame + droppedFrames + 1 : mCurrentFrame - droppedFrames - 1;
Dali::ClampInPlace(mCurrentFrame, mStartFrame, mEndFrame);
}
return frame;
}
-std::chrono::time_point<std::chrono::system_clock> VectorAnimationTask::CalculateNextFrameTime(bool renderNow)
+VectorAnimationTask::TimePoint VectorAnimationTask::CalculateNextFrameTime(bool renderNow)
{
+ uint32_t droppedFrames = 0;
+
// std::chrono::time_point template has second parameter duration which defaults to the std::chrono::system_clock supported
// duration. In some C++11 implementations it is a milliseconds duration, so it fails to compile unless mNextFrameStartTime
// is casted to use the default duration.
- mNextFrameStartTime = std::chrono::time_point_cast<std::chrono::time_point<std::chrono::system_clock>::duration>(
- mNextFrameStartTime + std::chrono::nanoseconds(mFrameDurationNanoSeconds));
- auto current = std::chrono::system_clock::now();
- if(renderNow || mNextFrameStartTime < current)
+ mNextFrameStartTime = std::chrono::time_point_cast<TimePoint::duration>(mNextFrameStartTime + std::chrono::microseconds(mFrameDurationMicroSeconds));
+ auto current = std::chrono::system_clock::now();
+ if(renderNow)
+ {
+ mNextFrameStartTime = current;
+ }
+ else if(mNextFrameStartTime < current)
{
+ while(current > std::chrono::time_point_cast<TimePoint::duration>(mNextFrameStartTime + std::chrono::microseconds(mFrameDurationMicroSeconds)))
+ {
+ droppedFrames++;
+ mNextFrameStartTime = std::chrono::time_point_cast<TimePoint::duration>(mNextFrameStartTime + std::chrono::microseconds(mFrameDurationMicroSeconds));
+ }
+
+ {
+ ConditionalWait::ScopedLock lock(mConditionalWait);
+ mDroppedFrames = droppedFrames;
+ }
+
mNextFrameStartTime = current;
}
+
return mNextFrameStartTime;
}
-std::chrono::time_point<std::chrono::system_clock> VectorAnimationTask::GetNextFrameTime()
+VectorAnimationTask::TimePoint VectorAnimationTask::GetNextFrameTime()
{
return mNextFrameStartTime;
}
public:
using UploadCompletedSignalType = Dali::VectorAnimationRenderer::UploadCompletedSignalType;
+ using TimePoint = std::chrono::time_point<std::chrono::system_clock>;
+
/**
* Flags for re-sending data to the vector animation thread
*/
* @brief Calculates the time for the next frame rasterization.
* @return The time for the next frame rasterization.
*/
- std::chrono::time_point<std::chrono::system_clock> CalculateNextFrameTime(bool renderNow);
+ TimePoint CalculateNextFrameTime(bool renderNow);
/**
* @brief Gets the time for the next frame rasterization.
* @return The time for the next frame rasterization.
*/
- std::chrono::time_point<std::chrono::system_clock> GetNextFrameTime();
+ TimePoint GetNextFrameTime();
private:
/**
PAUSED ///< The animation is paused
};
- std::string mUrl;
- VectorAnimationRenderer mVectorRenderer;
- AnimationData mAnimationData[2];
- VectorAnimationThread& mVectorAnimationThread;
- ConditionalWait mConditionalWait;
- std::unique_ptr<EventThreadCallback> mAnimationFinishedTrigger;
- PlayState mPlayState;
- DevelImageVisual::StopBehavior::Type mStopBehavior;
- DevelImageVisual::LoopingMode::Type mLoopingMode;
- std::chrono::time_point<std::chrono::system_clock> mNextFrameStartTime;
- int64_t mFrameDurationNanoSeconds;
- float mFrameRate;
- uint32_t mCurrentFrame;
- uint32_t mTotalFrame;
- uint32_t mStartFrame;
- uint32_t mEndFrame;
- uint32_t mWidth;
- uint32_t mHeight;
- uint32_t mAnimationDataIndex;
- int32_t mLoopCount;
- int32_t mCurrentLoop;
- bool mForward;
- bool mUpdateFrameNumber;
- bool mNeedAnimationFinishedTrigger;
- bool mAnimationDataUpdated;
- bool mDestroyTask;
+ std::string mUrl;
+ VectorAnimationRenderer mVectorRenderer;
+ AnimationData mAnimationData[2];
+ VectorAnimationThread& mVectorAnimationThread;
+ ConditionalWait mConditionalWait;
+ std::unique_ptr<EventThreadCallback> mAnimationFinishedTrigger;
+ PlayState mPlayState;
+ DevelImageVisual::StopBehavior::Type mStopBehavior;
+ DevelImageVisual::LoopingMode::Type mLoopingMode;
+ TimePoint mNextFrameStartTime;
+ int64_t mFrameDurationMicroSeconds;
+ float mFrameRate;
+ uint32_t mCurrentFrame;
+ uint32_t mTotalFrame;
+ uint32_t mStartFrame;
+ uint32_t mEndFrame;
+ uint32_t mDroppedFrames;
+ uint32_t mWidth;
+ uint32_t mHeight;
+ uint32_t mAnimationDataIndex;
+ int32_t mLoopCount;
+ int32_t mCurrentLoop;
+ bool mForward;
+ bool mUpdateFrameNumber;
+ bool mNeedAnimationFinishedTrigger;
+ bool mAnimationDataUpdated;
+ bool mDestroyTask;
};
} // namespace Internal
UnregisterProcessor();
}
-void SvgRasterizeThread::Process()
+void SvgRasterizeThread::Process(bool postProcessor)
{
ApplyRasterizedSVGToSampler();
}
/**
* @copydoc Dali::Integration::Processor::Process()
*/
- void Process() override;
+ void Process(bool postProcessor) override;
private:
/**
{
const unsigned int TOOLKIT_MAJOR_VERSION = 2;
const unsigned int TOOLKIT_MINOR_VERSION = 0;
-const unsigned int TOOLKIT_MICRO_VERSION = 22;
+const unsigned int TOOLKIT_MICRO_VERSION = 23;
const char* const TOOLKIT_BUILD_DATE = __DATE__ " " __TIME__;
#ifdef DEBUG_ENABLED
--- /dev/null
+/*
+ * Copyright (c) 2021 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 <algorithm>
+#include <filesystem>
+#include <fstream>
+#include <iostream>
+#include <string>
+#include <string_view>
+#include <vector>
+
+using namespace std;
+namespace fs = filesystem;
+
+namespace
+{
+///////////////////////////////////////////////////////////////////////////////////////////////////
+string PROGRAM_NAME; ///< We set the program name on this global early on for use in Usage.
+string_view VERSION = "1.0.0";
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/// Supported extensions for the files in the input directory.
+// clang-format off
+constexpr string_view SHADER_EXTENSIONS[] =
+{
+ ".vert",
+ ".frag",
+ ".def"
+};
+// clang-format on
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/// Function & variable to retrieve the size of the extension with the largest string size.
+constexpr auto GetShaderExtensionMaxSize()
+{
+ auto maxSize = 0u;
+ for(const auto& extension : SHADER_EXTENSIONS)
+ {
+ if(extension.size() > maxSize)
+ {
+ maxSize = extension.size();
+ }
+ }
+ return maxSize;
+}
+constexpr const int SHADER_MAX_EXTENSION_SIZE(GetShaderExtensionMaxSize());
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/// Prints out the Usage to standard output.
+void Usage()
+{
+ cout << "Usage: " << PROGRAM_NAME << " [OPTIONS] [IN_DIR] [OUT_DIR]" << endl;
+ cout << " IN_DIR: Input Directory which has all the shader files." << endl;
+ cout << " Supported extensions:";
+ string extensions;
+ for(const auto& extension : SHADER_EXTENSIONS)
+ {
+ extensions = extensions + " \"" + string(extension) + "\",";
+ }
+ extensions.pop_back(); // Remove the last comma.
+ cout << extensions << "." << endl;
+ cout << " OUT_DIR: Directory where the generated shader source code will be outputted to." << endl;
+ cout << " This directory will be created if it does not exist." << endl;
+ cout << " Any existing files of the same name in the directory will be overwritten." << endl;
+ cout << " Options: " << endl;
+ cout << " -s|--skip Skips the generation of the built-in header and source files" << endl;
+ cout << " -v|--version Prints out the version" << endl;
+ cout << " -h|--help Help" << endl;
+ cout << " NOTE: The options can be placed after the IN_DIR & OUT_DIR as well" << endl;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/// Uses the filename to generate the shader variable name to use in source code.
+/// @param[in] filename The filename of the shader (including the extension)
+/// @return The shader variable name
+string GetShaderVariableName(const string& filename)
+{
+ string shaderVariableName("SHADER_" + filename);
+ for_each(
+ shaderVariableName.begin(),
+ shaderVariableName.end(),
+ [](char& character) {
+ switch(character)
+ {
+ case '-':
+ case '.':
+ {
+ character = '_';
+ break;
+ }
+
+ default:
+ {
+ character = ::toupper(character);
+ break;
+ }
+ }
+ });
+ return shaderVariableName;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/// Uses the ourDir & filename to generate the path of the output header file for the shader.
+/// @param[in] outDir The directory where the readable shaders will be outputted to
+/// @param[in] filename The filename of the shader (including the extension)
+/// @return The path to the output file
+fs::path GetShaderOutputFilePath(fs::path& outDir, const string& filename)
+{
+ string outFilename(filename);
+ replace(outFilename.end() - SHADER_MAX_EXTENSION_SIZE, outFilename.end(), '.', '-');
+ outFilename = outDir.string() + "/" + outFilename + ".h";
+ return outFilename;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/// Generates the header file from the input shader file.
+/// @param[in] shaderFile The full path of the input shader file
+/// @param[in] shaderVariableName The variable name to use for the string_view
+/// @param[in] outFilePath The full path to the output file
+void GenerateHeaderFile(
+ ifstream& shaderFile,
+ const string& shaderVariableName,
+ const fs::path& outFilePath)
+{
+ cout << " Generating \"" << shaderVariableName << "\" in " << outFilePath.filename();
+ ofstream outFile(outFilePath);
+ if(outFile.is_open())
+ {
+ outFile << "#pragma once" << endl
+ << endl;
+ outFile << "const std::string_view " << shaderVariableName << endl;
+ outFile << "{" << endl;
+ string line;
+ while(getline(shaderFile, line))
+ {
+ outFile << "\"" << line << "\\n\"" << endl;
+ }
+ outFile << "};" << endl;
+ cout << " [OK]" << endl;
+ }
+ else
+ {
+ cout << " [FAIL]" << endl;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/// If required, this accumulates data about all the shaders & generates the built-in cpp & header
+class BuiltInFilesGenerator
+{
+public:
+ /// Constructor
+ /// @param[in] outDir The path to the output directory
+ BuiltInFilesGenerator(const fs::path& outDir)
+ : mHeaderFilePath(outDir.string() + "/../" + string(HEADER_FILE_NAME)),
+ mSourceFilePath(outDir.string() + "/" + string(SOURCE_FILE_NAME))
+ {
+ }
+
+ /// Default destructor
+ ~BuiltInFilesGenerator() = default;
+
+ /// Adds the variable and the header file name to the appropriate vectors.
+ /// @param[in] variableName The string_view variable name used
+ /// @param[in] headerFileName The name of the header used
+ void Add(string&& variableName, const std::string& headerFilename)
+ {
+ mVariableNames.emplace_back(variableName);
+ mHeaderFileNames.emplace_back(headerFilename);
+ }
+
+ // Generates the built in files.
+ void Generate()
+ {
+ GenerateFile(
+ mVariableNames,
+ mHeaderFilePath,
+ "#pragma once\n\n#include <string_view>\n\n",
+ "extern const std::string_view ",
+ ";");
+
+ GenerateFile(
+ mHeaderFileNames,
+ mSourceFilePath,
+ "#include \"../" + string(HEADER_FILE_NAME) + "\"\n\n",
+ "#include \"",
+ "\"");
+ }
+
+private:
+ /// Generates the required file.
+ /// @param[in] strings A reference to the vector to parse
+ /// @param[in] filePath Outputs the data to this file
+ /// @param[in] header Puts this before parsing any of the vector
+ /// @param[in] before For each string, puts this string before it on every line
+ /// @param[in] after For each string, puts this string after it on every line
+ void GenerateFile(
+ vector<string>& strings,
+ const string& filePath,
+ const string_view header,
+ const string_view before,
+ const string_view after)
+ {
+ sort(strings.begin(), strings.end());
+ cout << " Generating \"" << filePath << "\"";
+ ofstream outFile(filePath);
+ if(outFile)
+ {
+ outFile << header;
+ for(auto& current : strings)
+ {
+ outFile << before << current << after << endl;
+ }
+ cout << " [OK]" << endl;
+ }
+ else
+ {
+ cout << " [FAIL]" << endl;
+ }
+ }
+
+ constexpr static string_view HEADER_FILE_NAME = "builtin-shader-extern-gen.h";
+ constexpr static string_view SOURCE_FILE_NAME = "builtin-shader-gen.cpp";
+
+ const string mHeaderFilePath; ///< Path to the header file to generate
+ const string mSourceFilePath; ///< Path to the source file to generate
+ vector<string> mVariableNames; ///< Holds all the variable names added through Add
+ vector<string> mHeaderFileNames; ///< Holds all the header file names added through Add
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/// Generates the header files from the shaders in the input directory & built-in files if reqruied.
+///
+/// @param[in] inDir The directory where all the input shader source is
+/// @param[in] outDir The directory where the readable shaders will be outputted to
+/// @param[in] generateBuiltInFiles If true, we generate the built-in files as well
+/// @return 0 if successful, 1 if failure
+int GenerateShaderSources(fs::path inDir, fs::path outDir, const bool generateBuiltInFiles)
+{
+ if(!fs::is_directory(inDir))
+ {
+ cerr << "ERROR: " << inDir << " is not a valid directory" << endl;
+ Usage();
+ return 1;
+ }
+
+ try
+ {
+ fs::create_directories(outDir);
+ }
+ catch(...)
+ {
+ cerr << "ERROR: Unable to create directory " << outDir << endl;
+ return 1;
+ }
+
+ cout << "====================================================================" << endl;
+ cout << "Shader Input Directory: " << inDir << endl;
+ cout << "Shader Output Directory: " << outDir << endl;
+ cout << "====================================================================" << endl;
+
+ BuiltInFilesGenerator generator(outDir);
+
+ for(auto& file : fs::directory_iterator(inDir))
+ {
+ if(file.is_regular_file())
+ {
+ for(const auto& extension : SHADER_EXTENSIONS)
+ {
+ if(file.path().extension() == extension)
+ {
+ const fs::path& path(file.path());
+ const string filename(path.filename().string());
+ string shaderVariableName(GetShaderVariableName(filename));
+ ifstream shaderFile(path);
+ if(shaderFile.is_open())
+ {
+ fs::path outFilePath(GetShaderOutputFilePath(outDir, filename));
+ GenerateHeaderFile(shaderFile, shaderVariableName, outFilePath);
+ generator.Add(std::move(shaderVariableName), outFilePath.filename().string());
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ if(generateBuiltInFiles)
+ {
+ generator.Generate();
+ }
+
+ cout << "====================================================================" << endl;
+ return 0;
+}
+
+} // unnamed namespace
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/// MAIN.
+int main(int argc, char* argv[])
+{
+ PROGRAM_NAME = argv[0];
+
+ bool generateBuiltInFiles = true;
+
+ string inDir;
+ string outDir;
+
+ for(auto i = 1; i < argc; ++i)
+ {
+ string option(argv[i]);
+ if(option == "--skip" || option == "-s")
+ {
+ generateBuiltInFiles = false;
+ }
+ else if(option == "--help" || option == "-h")
+ {
+ cout << "DALi Shader Generator v" << VERSION << endl
+ << endl;
+ Usage();
+ return 0;
+ }
+ else if(option == "--version" || option == "-v")
+ {
+ cout << VERSION << endl;
+ return 0;
+ }
+ else if(*option.begin() == '-')
+ {
+ cerr << "ERROR: " << option << " is not a supported option" << endl;
+ Usage();
+ return 1;
+ }
+ else if(inDir.empty())
+ {
+ inDir = option;
+ }
+ else if(outDir.empty())
+ {
+ outDir = option;
+ }
+ else if(inDir.size() && outDir.size())
+ {
+ cerr << "ERROR: Too many options" << endl;
+ Usage();
+ return 1;
+ }
+ }
+
+ if(inDir.empty() || outDir.empty())
+ {
+ cerr << "ERROR: Both IN_DIR & OUT_DIR not provided" << endl;
+ Usage();
+ return 1;
+ }
+
+ return GenerateShaderSources(inDir, outDir, generateBuiltInFiles);
+}
Name: dali2-toolkit
Summary: Dali 3D engine Toolkit
-Version: 2.0.22
+Version: 2.0.23
Release: 1
Group: System/Libraries
License: Apache-2.0 and BSD-3-Clause and MIT
%defattr(-,root,root,-)
%{dev_include_path}/dali-toolkit/*
%{_libdir}/pkgconfig/dali2-toolkit.pc
+%{_bindir}/dali-shader-generator
%files resources_360x360
%manifest dali-toolkit-resources.manifest