X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Finternal%2Fupdate%2Frendering%2Fscene-graph-renderer.cpp;h=3c0653f56c453706f7d2033f78803596c0d94c95;hb=0ec8b37a80208c66d87e4322092d40694092bf81;hp=1039a8da1afd7660d91dd048c4feb57971db2ca6;hpb=a655572ea47581cebad010a722db91bae9984980;p=platform%2Fcore%2Fuifw%2Fdali-core.git diff --git a/dali/internal/update/rendering/scene-graph-renderer.cpp b/dali/internal/update/rendering/scene-graph-renderer.cpp index 1039a8d..3c0653f 100644 --- a/dali/internal/update/rendering/scene-graph-renderer.cpp +++ b/dali/internal/update/rendering/scene-graph-renderer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 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. @@ -18,18 +18,21 @@ #include "scene-graph-renderer.h" // INTERNAL INCLUDES +#include #include #include -#include -#include -#include -#include #include +#include #include #include #include -#include -#include +#include +#include +#include +#include +#include + +#include namespace Dali { @@ -39,63 +42,15 @@ namespace SceneGraph { namespace // unnamed namespace { +#ifdef DEBUG_ENABLED +Debug::Filter* gSceneGraphRendererLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_SG_RENDERER"); +#endif -const uint32_t UNIFORM_MAP_READY = 0; -const uint32_t COPY_UNIFORM_MAP = 1; -const uint32_t REGENERATE_UNIFORM_MAP = 2; - -//Memory pool used to allocate new renderers. Memory used by this pool will be released when shutting down DALi -MemoryPoolObjectAllocator gRendererMemoryPool; - -void AddMappings( CollectedUniformMap& localMap, const UniformMap& uniformMap ) +// Memory pool used to allocate new renderers. Memory used by this pool will be released when shutting down DALi +MemoryPoolObjectAllocator& GetRendererMemoryPool() { - // Iterate thru uniformMap. - // Any maps that aren't in localMap should be added in a single step - - // keep a static vector to avoid temporary heap allocation. - // As this function gets called only from update thread we don't have to - // make it thread safe (so no need to keep a thread_local variable). - static CollectedUniformMap newUniformMappings; - - newUniformMappings.Clear(); - - for( UniformMap::SizeType i = 0, count=uniformMap.Count(); iuniformNameHash == nameHash ) - { - if( map->uniformName == uniformMap[i].uniformName ) - { - found = true; - break; - } - } - } - if( !found ) - { - // it's a new mapping. Add raw ptr to temporary list - newUniformMappings.PushBack( &uniformMap[i] ); - } - } - - if( newUniformMappings.Count() > 0 ) - { - localMap.Reserve( localMap.Count() + newUniformMappings.Count() ); - - for( CollectedUniformMap::Iterator iter = newUniformMappings.Begin(), - end = newUniformMappings.End() ; - iter != end ; - ++iter ) - { - const UniformPropertyMapping* map = (*iter); - localMap.PushBack( map ); - } - } + static MemoryPoolObjectAllocator gRendererMemoryPool; + return gRendererMemoryPool; } // Flags for re-sending data to renderer. @@ -121,310 +76,309 @@ enum Flags RESEND_STENCIL_OPERATION_ON_Z_PASS = 1 << 17, RESEND_WRITE_TO_COLOR_BUFFER = 1 << 18, RESEND_SHADER = 1 << 19, - RESEND_DRAW_COMMANDS = 1 << 20 + RESEND_DRAW_COMMANDS = 1 << 20, + RESEND_SET_RENDER_CALLBACK = 1 << 21 }; } // Anonymous namespace -Renderer* Renderer::New() +RendererKey Renderer::NewKey() { - return new ( gRendererMemoryPool.AllocateRawThreadSafe() ) Renderer(); + void* ptr = GetRendererMemoryPool().AllocateRawThreadSafe(); + auto key = GetRendererMemoryPool().GetKeyFromPtr(static_cast(ptr)); + new(ptr) Renderer(); + return RendererKey(key); } Renderer::Renderer() -: mSceneController( nullptr ), - mRenderer( nullptr ), - mTextureSet( nullptr ), - mGeometry( nullptr ), - mShader( nullptr ), - mRenderDataProvider( nullptr ), - mBlendColor( nullptr ), - mStencilParameters( RenderMode::AUTO, StencilFunction::ALWAYS, 0xFF, 0x00, 0xFF, StencilOperation::KEEP, StencilOperation::KEEP, StencilOperation::KEEP ), - mIndexedDrawFirstElement( 0u ), - mIndexedDrawElementsCount( 0u ), - mBlendBitmask( 0u ), - mRegenerateUniformMap( 0u ), - mResendFlag( 0u ), - mDepthFunction( DepthFunction::LESS ), - mFaceCullingMode( FaceCullingMode::NONE ), - mBlendMode( BlendMode::AUTO ), - mDepthWriteMode( DepthWriteMode::AUTO ), - mDepthTestMode( DepthTestMode::AUTO ), - mRenderingBehavior( DevelRenderer::Rendering::IF_REQUIRED ), - mPremultipledAlphaEnabled( false ), - mOpacity( 1.0f ), - mDepthIndex( 0 ) -{ - mUniformMapChanged[0] = false; - mUniformMapChanged[1] = false; - - // Observe our own PropertyOwner's uniform map - AddUniformMapObserver( *this ); +: mSceneController(nullptr), + mRenderer{}, + mTextureSet(nullptr), + mGeometry(nullptr), + mShader(nullptr), + mBlendColor(nullptr), + mStencilParameters(RenderMode::AUTO, StencilFunction::ALWAYS, 0xFF, 0x00, 0xFF, StencilOperation::KEEP, StencilOperation::KEEP, StencilOperation::KEEP), + mIndexedDrawFirstElement(0u), + mIndexedDrawElementsCount(0u), + mBlendBitmask(0u), + mResendFlag(0u), + mDepthFunction(DepthFunction::LESS), + mFaceCullingMode(FaceCullingMode::NONE), + mBlendMode(BlendMode::AUTO), + mDepthWriteMode(DepthWriteMode::AUTO), + mDepthTestMode(DepthTestMode::AUTO), + mRenderingBehavior(DevelRenderer::Rendering::IF_REQUIRED), + mUpdateDecay(Renderer::Decay::INITIAL), + mRegenerateUniformMap(false), + mPremultipledAlphaEnabled(false), + mDirtyFlag(true), + mOpacity(1.0f), + mDepthIndex(0) +{ } Renderer::~Renderer() { - if( mTextureSet ) - { - mTextureSet->RemoveObserver( this ); - mTextureSet = nullptr; - } - if( mShader ) - { - mShader->RemoveConnectionObserver( *this ); - mShader = nullptr; - } } -void Renderer::operator delete( void* ptr ) +void Renderer::operator delete(void* ptr) { - gRendererMemoryPool.FreeThreadSafe( static_cast( ptr ) ); + GetRendererMemoryPool().FreeThreadSafe(static_cast(ptr)); } - -bool Renderer::PrepareRender( BufferIndex updateBufferIndex ) +Renderer* Renderer::Get(RendererKey::KeyType rendererKey) { - if( mRegenerateUniformMap == UNIFORM_MAP_READY ) - { - mUniformMapChanged[updateBufferIndex] = false; - } - else - { - if( mRegenerateUniformMap == REGENERATE_UNIFORM_MAP) - { - CollectedUniformMap& localMap = mCollectedUniformMap[ updateBufferIndex ]; - localMap.Resize(0); - - const UniformMap& rendererUniformMap = PropertyOwner::GetUniformMap(); - AddMappings( localMap, rendererUniformMap ); - - if( mShader ) - { - AddMappings( localMap, mShader->GetUniformMap() ); - } - } - else if( mRegenerateUniformMap == COPY_UNIFORM_MAP ) - { - // Copy old map into current map - CollectedUniformMap& localMap = mCollectedUniformMap[ updateBufferIndex ]; - CollectedUniformMap& oldMap = mCollectedUniformMap[ 1-updateBufferIndex ]; + return GetRendererMemoryPool().GetPtrFromKey(rendererKey); +} - localMap.Resize( oldMap.Count() ); +RendererKey Renderer::GetKey(const Renderer& renderer) +{ + return RendererKey(GetRendererMemoryPool().GetKeyFromPtr(const_cast(&renderer))); +} - uint32_t index=0; - for( CollectedUniformMap::Iterator iter = oldMap.Begin(), end = oldMap.End() ; iter != end ; ++iter, ++index ) - { - localMap[index] = *iter; - } - } +RendererKey Renderer::GetKey(Renderer* renderer) +{ + return RendererKey(GetRendererMemoryPool().GetKeyFromPtr(renderer)); +} - mUniformMapChanged[updateBufferIndex] = true; - mRegenerateUniformMap--; +bool Renderer::PrepareRender(BufferIndex updateBufferIndex) +{ + bool rendererUpdated = mResendFlag || mRenderingBehavior == DevelRenderer::Rendering::CONTINUOUSLY || mUpdateDecay > 0; + auto shaderMapChangeCounter = mShader ? mShader->GetUniformMap().GetChangeCounter() : 0u; + bool shaderMapChanged = mShader && (mShaderMapChangeCounter != shaderMapChangeCounter); + if(shaderMapChanged) + { + mShaderMapChangeCounter = shaderMapChangeCounter; } - bool rendererUpdated = mUniformMapChanged[updateBufferIndex] || mResendFlag; + if(mUniformMapChangeCounter != mUniformMaps.GetChangeCounter() || shaderMapChanged) + { + // The map has changed since the last time we checked. + rendererUpdated = true; + mRegenerateUniformMap = true; + mUpdateDecay = Renderer::Decay::INITIAL; // Render at least twice if the map has changed/actor has been added + + // Update local counters to identify any future changes to maps + // (unlikely, but allowed by API). + mUniformMapChangeCounter = mUniformMaps.GetChangeCounter(); + } + if(mUpdateDecay > 0) + { + mUpdateDecay = static_cast(static_cast(mUpdateDecay) - 1); + } - if( mResendFlag != 0 ) + if(mResendFlag != 0) { - if( mResendFlag & RESEND_GEOMETRY ) + Render::Renderer* rendererPtr = mRenderer.Get(); + if(mResendFlag & RESEND_GEOMETRY) { - typedef MessageValue1< Render::Renderer, Render::Geometry* > DerivedType; - uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) ); - new (slot) DerivedType( mRenderer, &Render::Renderer::SetGeometry, mGeometry ); + typedef MessageValue1 DerivedType; + uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot(updateBufferIndex, sizeof(DerivedType)); + new(slot) DerivedType(rendererPtr, &Render::Renderer::SetGeometry, mGeometry); } - if( mResendFlag & RESEND_DRAW_COMMANDS ) + if(mResendFlag & RESEND_DRAW_COMMANDS) { using DerivedType = MessageValue2; - uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) ); - new (slot) DerivedType( mRenderer, &Render::Renderer::SetDrawCommands, mDrawCommands.data(), mDrawCommands.size() ); + uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot(updateBufferIndex, sizeof(DerivedType)); + new(slot) DerivedType(rendererPtr, &Render::Renderer::SetDrawCommands, mDrawCommands.data(), mDrawCommands.size()); } - if( mResendFlag & RESEND_FACE_CULLING_MODE ) + if(mResendFlag & RESEND_FACE_CULLING_MODE) { using DerivedType = MessageValue1; - uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) ); - new (slot) DerivedType( mRenderer, &Render::Renderer::SetFaceCullingMode, mFaceCullingMode ); + uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot(updateBufferIndex, sizeof(DerivedType)); + new(slot) DerivedType(rendererPtr, &Render::Renderer::SetFaceCullingMode, mFaceCullingMode); } - if( mResendFlag & RESEND_BLEND_BIT_MASK ) + if(mResendFlag & RESEND_BLEND_BIT_MASK) { using DerivedType = MessageValue1; - uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) ); - new (slot) DerivedType( mRenderer, &Render::Renderer::SetBlendingBitMask, mBlendBitmask ); + uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot(updateBufferIndex, sizeof(DerivedType)); + new(slot) DerivedType(rendererPtr, &Render::Renderer::SetBlendingBitMask, mBlendBitmask); } - if( mResendFlag & RESEND_BLEND_COLOR ) + if(mResendFlag & RESEND_BLEND_COLOR) { using DerivedType = MessageValue1; - uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) ); - new (slot) DerivedType( mRenderer, &Render::Renderer::SetBlendColor, GetBlendColor() ); + uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot(updateBufferIndex, sizeof(DerivedType)); + new(slot) DerivedType(rendererPtr, &Render::Renderer::SetBlendColor, GetBlendColor()); } - if( mResendFlag & RESEND_PREMULTIPLIED_ALPHA ) + if(mResendFlag & RESEND_PREMULTIPLIED_ALPHA) { using DerivedType = MessageValue1; - uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) ); - new (slot) DerivedType( mRenderer, &Render::Renderer::EnablePreMultipliedAlpha, mPremultipledAlphaEnabled ); + uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot(updateBufferIndex, sizeof(DerivedType)); + new(slot) DerivedType(rendererPtr, &Render::Renderer::EnablePreMultipliedAlpha, mPremultipledAlphaEnabled); } - if( mResendFlag & RESEND_INDEXED_DRAW_FIRST_ELEMENT ) + if(mResendFlag & RESEND_INDEXED_DRAW_FIRST_ELEMENT) { using DerivedType = MessageValue1; - uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) ); - new (slot) DerivedType( mRenderer, &Render::Renderer::SetIndexedDrawFirstElement, mIndexedDrawFirstElement ); + uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot(updateBufferIndex, sizeof(DerivedType)); + new(slot) DerivedType(rendererPtr, &Render::Renderer::SetIndexedDrawFirstElement, mIndexedDrawFirstElement); } - if( mResendFlag & RESEND_INDEXED_DRAW_ELEMENTS_COUNT ) + if(mResendFlag & RESEND_INDEXED_DRAW_ELEMENTS_COUNT) { using DerivedType = MessageValue1; - uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) ); - new (slot) DerivedType( mRenderer, &Render::Renderer::SetIndexedDrawElementsCount, mIndexedDrawElementsCount ); + uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot(updateBufferIndex, sizeof(DerivedType)); + new(slot) DerivedType(rendererPtr, &Render::Renderer::SetIndexedDrawElementsCount, mIndexedDrawElementsCount); } - if( mResendFlag & RESEND_DEPTH_WRITE_MODE ) + if(mResendFlag & RESEND_DEPTH_WRITE_MODE) { using DerivedType = MessageValue1; - uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) ); - new (slot) DerivedType( mRenderer, &Render::Renderer::SetDepthWriteMode, mDepthWriteMode ); + uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot(updateBufferIndex, sizeof(DerivedType)); + new(slot) DerivedType(rendererPtr, &Render::Renderer::SetDepthWriteMode, mDepthWriteMode); } - if( mResendFlag & RESEND_DEPTH_TEST_MODE ) + if(mResendFlag & RESEND_DEPTH_TEST_MODE) { using DerivedType = MessageValue1; - uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) ); - new (slot) DerivedType( mRenderer, &Render::Renderer::SetDepthTestMode, mDepthTestMode ); + uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot(updateBufferIndex, sizeof(DerivedType)); + new(slot) DerivedType(rendererPtr, &Render::Renderer::SetDepthTestMode, mDepthTestMode); } - if( mResendFlag & RESEND_DEPTH_FUNCTION ) + if(mResendFlag & RESEND_DEPTH_FUNCTION) { using DerivedType = MessageValue1; - uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) ); - new (slot) DerivedType( mRenderer, &Render::Renderer::SetDepthFunction, mDepthFunction ); + uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot(updateBufferIndex, sizeof(DerivedType)); + new(slot) DerivedType(rendererPtr, &Render::Renderer::SetDepthFunction, mDepthFunction); } - if( mResendFlag & RESEND_RENDER_MODE ) + if(mResendFlag & RESEND_RENDER_MODE) { using DerivedType = MessageValue1; - uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) ); - new (slot) DerivedType( mRenderer, &Render::Renderer::SetRenderMode, mStencilParameters.renderMode ); + uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot(updateBufferIndex, sizeof(DerivedType)); + new(slot) DerivedType(rendererPtr, &Render::Renderer::SetRenderMode, mStencilParameters.renderMode); } - if( mResendFlag & RESEND_STENCIL_FUNCTION ) + if(mResendFlag & RESEND_STENCIL_FUNCTION) { using DerivedType = MessageValue1; - uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) ); - new (slot) DerivedType( mRenderer, &Render::Renderer::SetStencilFunction, mStencilParameters.stencilFunction ); + uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot(updateBufferIndex, sizeof(DerivedType)); + new(slot) DerivedType(rendererPtr, &Render::Renderer::SetStencilFunction, mStencilParameters.stencilFunction); } - if( mResendFlag & RESEND_STENCIL_FUNCTION_MASK ) + if(mResendFlag & RESEND_STENCIL_FUNCTION_MASK) { using DerivedType = MessageValue1; - uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) ); - new (slot) DerivedType( mRenderer, &Render::Renderer::SetStencilFunctionMask, mStencilParameters.stencilFunctionMask ); + uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot(updateBufferIndex, sizeof(DerivedType)); + new(slot) DerivedType(rendererPtr, &Render::Renderer::SetStencilFunctionMask, mStencilParameters.stencilFunctionMask); } - if( mResendFlag & RESEND_STENCIL_FUNCTION_REFERENCE ) + if(mResendFlag & RESEND_STENCIL_FUNCTION_REFERENCE) { using DerivedType = MessageValue1; - uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) ); - new (slot) DerivedType( mRenderer, &Render::Renderer::SetStencilFunctionReference, mStencilParameters.stencilFunctionReference ); + uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot(updateBufferIndex, sizeof(DerivedType)); + new(slot) DerivedType(rendererPtr, &Render::Renderer::SetStencilFunctionReference, mStencilParameters.stencilFunctionReference); } - if( mResendFlag & RESEND_STENCIL_MASK ) + if(mResendFlag & RESEND_STENCIL_MASK) { using DerivedType = MessageValue1; - uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) ); - new (slot) DerivedType( mRenderer, &Render::Renderer::SetStencilMask, mStencilParameters.stencilMask ); + uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot(updateBufferIndex, sizeof(DerivedType)); + new(slot) DerivedType(rendererPtr, &Render::Renderer::SetStencilMask, mStencilParameters.stencilMask); } - if( mResendFlag & RESEND_STENCIL_OPERATION_ON_FAIL ) + if(mResendFlag & RESEND_STENCIL_OPERATION_ON_FAIL) { using DerivedType = MessageValue1; - uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) ); - new (slot) DerivedType( mRenderer, &Render::Renderer::SetStencilOperationOnFail, mStencilParameters.stencilOperationOnFail ); + uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot(updateBufferIndex, sizeof(DerivedType)); + new(slot) DerivedType(rendererPtr, &Render::Renderer::SetStencilOperationOnFail, mStencilParameters.stencilOperationOnFail); } - if( mResendFlag & RESEND_STENCIL_OPERATION_ON_Z_FAIL ) + if(mResendFlag & RESEND_STENCIL_OPERATION_ON_Z_FAIL) { using DerivedType = MessageValue1; - uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) ); - new (slot) DerivedType( mRenderer, &Render::Renderer::SetStencilOperationOnZFail, mStencilParameters.stencilOperationOnZFail ); + uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot(updateBufferIndex, sizeof(DerivedType)); + new(slot) DerivedType(rendererPtr, &Render::Renderer::SetStencilOperationOnZFail, mStencilParameters.stencilOperationOnZFail); } - if( mResendFlag & RESEND_STENCIL_OPERATION_ON_Z_PASS ) + if(mResendFlag & RESEND_STENCIL_OPERATION_ON_Z_PASS) { using DerivedType = MessageValue1; - uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) ); - new (slot) DerivedType( mRenderer, &Render::Renderer::SetStencilOperationOnZPass, mStencilParameters.stencilOperationOnZPass ); + uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot(updateBufferIndex, sizeof(DerivedType)); + new(slot) DerivedType(rendererPtr, &Render::Renderer::SetStencilOperationOnZPass, mStencilParameters.stencilOperationOnZPass); } - if( mResendFlag & RESEND_SHADER ) + if(mResendFlag & RESEND_SHADER) { using DerivedType = MessageValue1; - uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) ); - new (slot) DerivedType( mRenderer, &Render::Renderer::SetShaderChanged, true ); + uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot(updateBufferIndex, sizeof(DerivedType)); + new(slot) DerivedType(rendererPtr, &Render::Renderer::SetShaderChanged, true); } + if(mResendFlag & RESEND_SET_RENDER_CALLBACK) + { + using DerivedType = MessageValue1; + uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot(updateBufferIndex, sizeof(DerivedType)); + new(slot) DerivedType(rendererPtr, &Render::Renderer::SetRenderCallback, mRenderCallback); + } + + SetUpdated(true); + mResendFlag = 0; } + // Ensure collected map is up to date + UpdateUniformMap(updateBufferIndex); + return rendererUpdated; } -void Renderer::SetTextures( TextureSet* textureSet ) +void Renderer::SetTextures(TextureSet* textureSet) { - DALI_ASSERT_DEBUG( textureSet != NULL && "Texture set pointer is NULL" ); - - if( mTextureSet ) - { - mTextureSet->RemoveObserver(this); - } + DALI_ASSERT_DEBUG(textureSet != NULL && "Texture set pointer is NULL"); mTextureSet = textureSet; - mTextureSet->AddObserver( this ); - mRegenerateUniformMap = REGENERATE_UNIFORM_MAP; - UpdateTextureSet(); + mDirtyFlag = true; + SetUpdated(true); } -void Renderer::SetShader( Shader* shader ) +const Vector* Renderer::GetTextures() const { - DALI_ASSERT_DEBUG( shader != NULL && "Shader pointer is NULL" ); + return mTextureSet ? &(mTextureSet->GetTextures()) : nullptr; +} - if( mShader ) - { - mShader->RemoveConnectionObserver(*this); - } +const Vector* Renderer::GetSamplers() const +{ + return mTextureSet ? &(mTextureSet->GetSamplers()) : nullptr; +} - mShader = shader; - mShader->AddConnectionObserver( *this ); - mRegenerateUniformMap = REGENERATE_UNIFORM_MAP; - mResendFlag |= RESEND_GEOMETRY | RESEND_SHADER; +void Renderer::SetShader(Shader* shader) +{ + DALI_ASSERT_DEBUG(shader != NULL && "Shader pointer is NULL"); - if( mRenderDataProvider ) - { - mRenderDataProvider->mShader = mShader; - } + mShader = shader; + mShaderMapChangeCounter = 0u; + mRegenerateUniformMap = true; + mResendFlag |= RESEND_GEOMETRY | RESEND_SHADER; + mDirtyFlag = true; } -void Renderer::SetGeometry( Render::Geometry* geometry ) +void Renderer::SetGeometry(Render::Geometry* geometry) { - DALI_ASSERT_DEBUG( geometry != NULL && "Geometry pointer is NULL"); + DALI_ASSERT_DEBUG(geometry != NULL && "Geometry pointer is NULL"); mGeometry = geometry; - if( mRenderer ) + if(mRenderer) { mResendFlag |= RESEND_GEOMETRY; } } -void Renderer::SetDepthIndex( int depthIndex ) +void Renderer::SetDepthIndex(int depthIndex) { mDepthIndex = depthIndex; + + mDirtyFlag = true; + SetUpdated(true); } -void Renderer::SetFaceCullingMode( FaceCullingMode::Type faceCullingMode ) +void Renderer::SetFaceCullingMode(FaceCullingMode::Type faceCullingMode) { mFaceCullingMode = faceCullingMode; mResendFlag |= RESEND_FACE_CULLING_MODE; @@ -435,9 +389,12 @@ FaceCullingMode::Type Renderer::GetFaceCullingMode() const return mFaceCullingMode; } -void Renderer::SetBlendMode( BlendMode::Type blendingMode ) +void Renderer::SetBlendMode(BlendMode::Type blendingMode) { mBlendMode = blendingMode; + + mDirtyFlag = true; + SetUpdated(true); } BlendMode::Type Renderer::GetBlendMode() const @@ -445,12 +402,13 @@ BlendMode::Type Renderer::GetBlendMode() const return mBlendMode; } -void Renderer::SetBlendingOptions( uint32_t options ) +void Renderer::SetBlendingOptions(uint32_t options) { - if( mBlendBitmask != options) + if(mBlendBitmask != options) { mBlendBitmask = options; mResendFlag |= RESEND_BLEND_BIT_MASK; + mDirtyFlag = true; } } @@ -459,17 +417,17 @@ uint32_t Renderer::GetBlendingOptions() const return mBlendBitmask; } -void Renderer::SetBlendColor( const Vector4& blendColor ) +void Renderer::SetBlendColor(const Vector4& blendColor) { - if( blendColor == Color::TRANSPARENT ) + if(blendColor == Color::TRANSPARENT) { mBlendColor = nullptr; } else { - if( !mBlendColor ) + if(!mBlendColor) { - mBlendColor = new Vector4( blendColor ); + mBlendColor = new Vector4(blendColor); } else { @@ -482,14 +440,14 @@ void Renderer::SetBlendColor( const Vector4& blendColor ) Vector4 Renderer::GetBlendColor() const { - if( mBlendColor ) + if(mBlendColor) { return *mBlendColor; } return Color::TRANSPARENT; } -void Renderer::SetIndexedDrawFirstElement( uint32_t firstElement ) +void Renderer::SetIndexedDrawFirstElement(uint32_t firstElement) { mIndexedDrawFirstElement = firstElement; mResendFlag |= RESEND_INDEXED_DRAW_FIRST_ELEMENT; @@ -500,7 +458,7 @@ uint32_t Renderer::GetIndexedDrawFirstElement() const return mIndexedDrawFirstElement; } -void Renderer::SetIndexedDrawElementsCount( uint32_t elementsCount ) +void Renderer::SetIndexedDrawElementsCount(uint32_t elementsCount) { mIndexedDrawElementsCount = elementsCount; mResendFlag |= RESEND_INDEXED_DRAW_ELEMENTS_COUNT; @@ -511,7 +469,7 @@ uint32_t Renderer::GetIndexedDrawElementsCount() const return mIndexedDrawElementsCount; } -void Renderer::EnablePreMultipliedAlpha( bool preMultipled ) +void Renderer::EnablePreMultipliedAlpha(bool preMultipled) { mPremultipledAlphaEnabled = preMultipled; mResendFlag |= RESEND_PREMULTIPLIED_ALPHA; @@ -522,7 +480,7 @@ bool Renderer::IsPreMultipliedAlphaEnabled() const return mPremultipledAlphaEnabled; } -void Renderer::SetDepthWriteMode( DepthWriteMode::Type depthWriteMode ) +void Renderer::SetDepthWriteMode(DepthWriteMode::Type depthWriteMode) { mDepthWriteMode = depthWriteMode; mResendFlag |= RESEND_DEPTH_WRITE_MODE; @@ -533,7 +491,7 @@ DepthWriteMode::Type Renderer::GetDepthWriteMode() const return mDepthWriteMode; } -void Renderer::SetDepthTestMode( DepthTestMode::Type depthTestMode ) +void Renderer::SetDepthTestMode(DepthTestMode::Type depthTestMode) { mDepthTestMode = depthTestMode; mResendFlag |= RESEND_DEPTH_TEST_MODE; @@ -544,7 +502,7 @@ DepthTestMode::Type Renderer::GetDepthTestMode() const return mDepthTestMode; } -void Renderer::SetDepthFunction( DepthFunction::Type depthFunction ) +void Renderer::SetDepthFunction(DepthFunction::Type depthFunction) { mDepthFunction = depthFunction; mResendFlag |= RESEND_DEPTH_FUNCTION; @@ -555,72 +513,83 @@ DepthFunction::Type Renderer::GetDepthFunction() const return mDepthFunction; } -void Renderer::SetRenderMode( RenderMode::Type mode ) +void Renderer::SetRenderMode(RenderMode::Type mode) { mStencilParameters.renderMode = mode; mResendFlag |= RESEND_RENDER_MODE; } -void Renderer::SetStencilFunction( StencilFunction::Type stencilFunction ) +void Renderer::SetStencilFunction(StencilFunction::Type stencilFunction) { mStencilParameters.stencilFunction = stencilFunction; mResendFlag |= RESEND_STENCIL_FUNCTION; } -void Renderer::SetStencilFunctionMask( int stencilFunctionMask ) +void Renderer::SetStencilFunctionMask(int stencilFunctionMask) { mStencilParameters.stencilFunctionMask = stencilFunctionMask; mResendFlag |= RESEND_STENCIL_FUNCTION_MASK; } -void Renderer::SetStencilFunctionReference( int stencilFunctionReference ) +void Renderer::SetStencilFunctionReference(int stencilFunctionReference) { mStencilParameters.stencilFunctionReference = stencilFunctionReference; mResendFlag |= RESEND_STENCIL_FUNCTION_REFERENCE; } -void Renderer::SetStencilMask( int stencilMask ) +void Renderer::SetStencilMask(int stencilMask) { mStencilParameters.stencilMask = stencilMask; mResendFlag |= RESEND_STENCIL_MASK; } -void Renderer::SetStencilOperationOnFail( StencilOperation::Type stencilOperationOnFail ) +void Renderer::SetStencilOperationOnFail(StencilOperation::Type stencilOperationOnFail) { mStencilParameters.stencilOperationOnFail = stencilOperationOnFail; mResendFlag |= RESEND_STENCIL_OPERATION_ON_FAIL; } -void Renderer::SetStencilOperationOnZFail( StencilOperation::Type stencilOperationOnZFail ) +void Renderer::SetStencilOperationOnZFail(StencilOperation::Type stencilOperationOnZFail) { mStencilParameters.stencilOperationOnZFail = stencilOperationOnZFail; mResendFlag |= RESEND_STENCIL_OPERATION_ON_Z_FAIL; } -void Renderer::SetStencilOperationOnZPass( StencilOperation::Type stencilOperationOnZPass ) +void Renderer::SetStencilOperationOnZPass(StencilOperation::Type stencilOperationOnZPass) { mStencilParameters.stencilOperationOnZPass = stencilOperationOnZPass; mResendFlag |= RESEND_STENCIL_OPERATION_ON_Z_PASS; } +void Renderer::SetRenderCallback(RenderCallback* callback) +{ + mRenderCallback = callback; + mResendFlag |= RESEND_SET_RENDER_CALLBACK; + mDirtyFlag = true; +} + const Render::Renderer::StencilParameters& Renderer::GetStencilParameters() const { return mStencilParameters; } -void Renderer::BakeOpacity( BufferIndex updateBufferIndex, float opacity ) +void Renderer::BakeOpacity(BufferIndex updateBufferIndex, float opacity) { - mOpacity.Bake( updateBufferIndex, opacity ); + mOpacity.Bake(updateBufferIndex, opacity); + + mDirtyFlag = true; + SetUpdated(true); } -float Renderer::GetOpacity( BufferIndex updateBufferIndex ) const +float Renderer::GetOpacity(BufferIndex updateBufferIndex) const { return mOpacity[updateBufferIndex]; } -void Renderer::SetRenderingBehavior( DevelRenderer::Rendering::Type renderingBehavior ) +void Renderer::SetRenderingBehavior(DevelRenderer::Rendering::Type renderingBehavior) { mRenderingBehavior = renderingBehavior; + SetUpdated(true); } DevelRenderer::Rendering::Type Renderer::GetRenderingBehavior() const @@ -628,78 +597,54 @@ DevelRenderer::Rendering::Type Renderer::GetRenderingBehavior() const return mRenderingBehavior; } -//Called when SceneGraph::Renderer is added to update manager ( that happens when an "event-thread renderer" is created ) -void Renderer::ConnectToSceneGraph( SceneController& sceneController, BufferIndex bufferIndex ) +// Called when SceneGraph::Renderer is added to update manager ( that happens when an "event-thread renderer" is created ) +void Renderer::ConnectToSceneGraph(SceneController& sceneController, BufferIndex bufferIndex) { - mRegenerateUniformMap = REGENERATE_UNIFORM_MAP; - mSceneController = &sceneController; - - mRenderDataProvider = new RenderDataProvider( mOpacity ); - mRenderDataProvider->mUniformMapDataProvider = this; + mRegenerateUniformMap = true; + mSceneController = &sceneController; - mRenderer = Render::Renderer::New( mRenderDataProvider, mGeometry, mBlendBitmask, GetBlendColor(), static_cast< FaceCullingMode::Type >( mFaceCullingMode ), - mPremultipledAlphaEnabled, mDepthWriteMode, mDepthTestMode, mDepthFunction, mStencilParameters ); + mRenderer = Render::Renderer::NewKey(this, mGeometry, mBlendBitmask, GetBlendColor(), static_cast(mFaceCullingMode), mPremultipledAlphaEnabled, mDepthWriteMode, mDepthTestMode, mDepthFunction, mStencilParameters); - OwnerPointer< Render::Renderer > transferOwnership( mRenderer ); - mSceneController->GetRenderMessageDispatcher().AddRenderer( transferOwnership ); + mSceneController->GetRenderMessageDispatcher().AddRenderer(mRenderer); } -//Called just before destroying the scene-graph renderer ( when the "event-thread renderer" is no longer referenced ) -void Renderer::DisconnectFromSceneGraph( SceneController& sceneController, BufferIndex bufferIndex ) +// Called just before destroying the scene-graph renderer ( when the "event-thread renderer" is no longer referenced ) +void Renderer::DisconnectFromSceneGraph(SceneController& sceneController, BufferIndex bufferIndex) { - //Remove renderer from RenderManager - if( mRenderer ) + // Remove renderer from RenderManager + if(mRenderer) { - mSceneController->GetRenderMessageDispatcher().RemoveRenderer( *mRenderer ); - mRenderer = nullptr; + mSceneController->GetRenderMessageDispatcher().RemoveRenderer(mRenderer); + mRenderer = Render::RendererKey{}; } mSceneController = nullptr; - mRenderDataProvider = nullptr; -} - -void Renderer::UpdateTextureSet() -{ - if( mRenderDataProvider ) - { - if( mTextureSet ) - { - uint32_t textureCount = mTextureSet->GetTextureCount(); - mRenderDataProvider->mTextures.resize( textureCount ); - mRenderDataProvider->mSamplers.resize( textureCount ); - for( uint32_t i = 0; imTextures[i] = mTextureSet->GetTexture(i); - mRenderDataProvider->mSamplers[i] = mTextureSet->GetTextureSampler(i); - } - } - else - { - mRenderDataProvider->mTextures.clear(); - mRenderDataProvider->mSamplers.clear(); - } - } } -Render::Renderer& Renderer::GetRenderer() +Render::RendererKey Renderer::GetRenderer() { - return *mRenderer; + return mRenderer; } -const CollectedUniformMap& Renderer::GetUniformMap( BufferIndex bufferIndex ) const -{ - return mCollectedUniformMap[bufferIndex]; -} - -Renderer::OpacityType Renderer::GetOpacityType( BufferIndex updateBufferIndex, const Node& node ) const +Renderer::OpacityType Renderer::GetOpacityType(BufferIndex updateBufferIndex, const Node& node) const { Renderer::OpacityType opacityType = Renderer::OPAQUE; - switch( mBlendMode ) + if(node.IsTransparent()) + { + return Renderer::TRANSPARENT; + } + + switch(mBlendMode) { + case BlendMode::ON_WITHOUT_CULL: // If the renderer should always be use blending and never want to be transparent by alpha. + { + opacityType = Renderer::TRANSLUCENT; + break; + } case BlendMode::ON: // If the renderer should always be use blending { - float alpha = node.GetWorldColor( updateBufferIndex ).a * mOpacity[updateBufferIndex]; - if( alpha <= FULLY_TRANSPARENT ) + float alpha = node.GetWorldColor(updateBufferIndex).a * mOpacity[updateBufferIndex]; + if(alpha <= FULLY_TRANSPARENT) { opacityType = Renderer::TRANSPARENT; } @@ -717,25 +662,43 @@ Renderer::OpacityType Renderer::GetOpacityType( BufferIndex updateBufferIndex, c break; } - bool shaderRequiresBlending( mShader->HintEnabled( Dali::Shader::Hint::OUTPUT_IS_TRANSPARENT ) ); - if( shaderRequiresBlending || ( mTextureSet && mTextureSet->HasAlpha() ) ) + bool shaderRequiresBlending(mShader->HintEnabled(Dali::Shader::Hint::OUTPUT_IS_TRANSPARENT)); + if(shaderRequiresBlending || (mTextureSet && mTextureSet->HasAlpha())) { opacityType = Renderer::TRANSLUCENT; } // renderer should determine opacity using the actor color - float alpha = node.GetWorldColor( updateBufferIndex ).a * mOpacity[updateBufferIndex]; - if( alpha <= FULLY_TRANSPARENT ) + float alpha = node.GetWorldColor(updateBufferIndex).a * mOpacity[updateBufferIndex]; + if(alpha <= FULLY_TRANSPARENT) { opacityType = Renderer::TRANSPARENT; } - else if( alpha <= FULLY_OPAQUE ) + else if(alpha <= FULLY_OPAQUE) { opacityType = Renderer::TRANSLUCENT; } break; } + case BlendMode::USE_ACTOR_OPACITY: // the renderer should never use blending + { + // renderer should determine opacity using the actor color + float alpha = node.GetWorldColor(updateBufferIndex).a; + if(alpha <= FULLY_TRANSPARENT) + { + opacityType = Renderer::TRANSPARENT; + } + else if(alpha < FULLY_OPAQUE) + { + opacityType = Renderer::TRANSLUCENT; + } + else + { + opacityType = Renderer::OPAQUE; + } + break; + } case BlendMode::OFF: // the renderer should never use blending default: { @@ -747,53 +710,216 @@ Renderer::OpacityType Renderer::GetOpacityType( BufferIndex updateBufferIndex, c return opacityType; } -void Renderer::TextureSetChanged() +void Renderer::UpdateUniformMap(BufferIndex updateBufferIndex) { - mRegenerateUniformMap = REGENERATE_UNIFORM_MAP; + if(mRegenerateUniformMap) + { + CollectedUniformMap& localMap = mCollectedUniformMap; + localMap.Clear(); + + const UniformMap& rendererUniformMap = PropertyOwner::GetUniformMap(); - UpdateTextureSet(); + auto size = rendererUniformMap.Count(); + if(mShader) + { + size += mShader->GetUniformMap().Count(); + } + + localMap.Reserve(size); + localMap.AddMappings(rendererUniformMap); + if(mShader) + { + localMap.AddMappings(mShader->GetUniformMap()); + } + localMap.UpdateChangeCounter(); + + mRegenerateUniformMap = false; + SetUpdated(true); + } } -void Renderer::TextureSetDeleted() +void Renderer::SetDrawCommands(Dali::DevelRenderer::DrawCommand* pDrawCommands, uint32_t size) { - mTextureSet = nullptr; + mDrawCommands.clear(); + mDrawCommands.insert(mDrawCommands.end(), pDrawCommands, pDrawCommands + size); + mResendFlag |= RESEND_DRAW_COMMANDS; +} - mRegenerateUniformMap = REGENERATE_UNIFORM_MAP; +bool Renderer::IsDirty() const +{ + // Check whether the opacity property has changed + return (mDirtyFlag || !mOpacity.IsClean()); +} + +void Renderer::ResetDirtyFlag() +{ + mDirtyFlag = false; - UpdateTextureSet(); + SetUpdated(false); } -void Renderer::ConnectionsChanged( PropertyOwner& object ) +uint32_t Renderer::GetMemoryPoolCapacity() { - // One of our child objects has changed it's connections. Ensure the uniform - // map gets regenerated during PrepareRender - mRegenerateUniformMap = REGENERATE_UNIFORM_MAP; + return GetRendererMemoryPool().GetCapacity(); } -void Renderer::ConnectedUniformMapChanged() +void Renderer::OnMappingChanged() { - mRegenerateUniformMap = REGENERATE_UNIFORM_MAP; + // Properties have been registered on the base class. + mRegenerateUniformMap = true; // Should remain true until this renderer is added to a RenderList. } -void Renderer::UniformMappingsChanged( const UniformMap& mappings ) +const CollectedUniformMap& Renderer::GetCollectedUniformMap() const { - // The mappings are either from PropertyOwner base class, or the Actor - mRegenerateUniformMap = REGENERATE_UNIFORM_MAP; + return mCollectedUniformMap; } -void Renderer::ObservedObjectDestroyed(PropertyOwner& owner) +bool Renderer::IsUpdated() const { - if( reinterpret_cast(mShader) == &owner ) + if(Updated() || (mShader && mShader->Updated())) { - mShader = nullptr; + return true; } + return false; } -void Renderer::SetDrawCommands( Dali::DevelRenderer::DrawCommand* pDrawCommands, uint32_t size ) +Vector4 Renderer::GetVisualTransformedUpdateArea(BufferIndex updateBufferIndex, const Vector4& originalUpdateArea) noexcept { - mDrawCommands.clear(); - mDrawCommands.insert( mDrawCommands.end(), pDrawCommands, pDrawCommands+size ); - mResendFlag |= RESEND_DRAW_COMMANDS; + if(mVisualProperties) + { + auto& coefficient = mVisualProperties->mCoefficient; + + // TODO : We may need to get some method that visual properties changed, without hash. + // Or, need to call this API in PreRender side. + + uint64_t hash = 0xc70f6907UL; + + hash = mVisualProperties->mTransformOffset.Hash(updateBufferIndex, hash); + hash = mVisualProperties->mTransformOffsetSizeMode.Hash(updateBufferIndex, hash); + hash = mVisualProperties->mTransformSize.Hash(updateBufferIndex, hash); + hash = mVisualProperties->mTransformOrigin.Hash(updateBufferIndex, hash); + hash = mVisualProperties->mTransformAnchorPoint.Hash(updateBufferIndex, hash); + hash = mVisualProperties->mExtraSize.Hash(updateBufferIndex, hash); + + if(coefficient.hash != hash) + { + coefficient.hash = hash; + + // VisualProperty + const Vector2 transformOffset = mVisualProperties->mTransformOffset.Get(updateBufferIndex); + const Vector4 transformOffsetSizeMode = mVisualProperties->mTransformOffsetSizeMode.Get(updateBufferIndex); + const Vector2 transformSize = mVisualProperties->mTransformSize.Get(updateBufferIndex); + const Vector2 transformOrigin = mVisualProperties->mTransformOrigin.Get(updateBufferIndex); + const Vector2 transformAnchorPoint = mVisualProperties->mTransformAnchorPoint.Get(updateBufferIndex); + const Vector2 extraSize = mVisualProperties->mExtraSize.Get(updateBufferIndex); + + DALI_LOG_INFO(gSceneGraphRendererLogFilter, Debug::Verbose, "transform size %5.3f %5.3f\n", transformSize.x, transformSize.y); + DALI_LOG_INFO(gSceneGraphRendererLogFilter, Debug::Verbose, "transform offset %5.3f %5.3f\n", transformOffset.x, transformOffset.y); + DALI_LOG_INFO(gSceneGraphRendererLogFilter, Debug::Verbose, "transform origin %5.3f %5.3f\n", transformOrigin.x, transformOrigin.y); + DALI_LOG_INFO(gSceneGraphRendererLogFilter, Debug::Verbose, "transform anchor %5.3f %5.3f\n", transformAnchorPoint.x, transformAnchorPoint.y); + DALI_LOG_INFO(gSceneGraphRendererLogFilter, Debug::Verbose, "extra size %5.3f %5.3f\n", extraSize.x, extraSize.y); + + // const Vector2 visualSize = Vector2(Dali::Lerp(transformOffsetSizeMode.z, originalSize.x * transformSize.x, transformSize.x), + // Dali::Lerp(transformOffsetSizeMode.w, originalSize.y * transformSize.y, transformSize.y)) + + // extraSize; + // const Vector2 visualOffset = Vector2(Dali::Lerp(transformOffsetSizeMode.x, originalSize.x * transformOffset.x, transformOffset.x), + // Dali::Lerp(transformOffsetSizeMode.y, originalSize.y * transformOffset.y, transformOffset.y)); + + // const float decoratedBorderlineWidth = std::max((1.0f + Dali::Clamp(borderlineOffset, -1.0f, 1.0f)) * borderlineWidth, 2.0f * blurRadius); + // const Vector2 decoratedVisualSize = visualSize + Vector2(decoratedBorderlineWidth, decoratedBorderlineWidth); + + // Note : vertexPositoin.xy = aPosition * decoratedVisualSize + // + anchorPoint * visualSize + // + origin * uSize.xy + // + visualOffset; + + // Calculate same logic of visual's vertex shader transform. + // minVertexPosition = -0.5f * decoratedVisualSize + transformAnchorPoint * visualSize + transformOrigin * originalSize.xy + visualOffset + // maxVertexPosition = 0.5f * decoratedVisualSize + transformAnchorPoint * visualSize + transformOrigin * originalSize.xy + visualOffset + + // Update cached VisualTransformedUpdateSizeCoefficientCache + + // Note : vertexPosition = (XA * aPosition + XB) * originalSize + (CA * aPosition + CB) + Vector2(D, D) * aPosition + + // XA = transformSize * (1.0 - transformOffsetSizeMode.zw) + // XB = transformSize * (1.0 - transformOffsetSizeMode.zw) * transformAnchorPoint + // + transformOffset * (1.0 - transformOffsetSizeMode.xy) + // + transformOrigin + // CA = transformSize * transformOffsetSizeMode.zw + extraSize + // CB = (transformSize * transformOffsetSizeMode.zw + extraSize) * transformAnchorPoint + // + transformOffset * transformOffsetSizeMode.xy + // D = max((1.0 + clamp(borderlineOffset, -1.0, 1.0)) * borderlineWidth, 2.0 * blurRadius) + + coefficient.coefXA = transformSize * Vector2(1.0f - transformOffsetSizeMode.z, 1.0f - transformOffsetSizeMode.w); + coefficient.coefXB = coefficient.coefXA * transformAnchorPoint + transformOffset * Vector2(1.0f - transformOffsetSizeMode.x, 1.0f - transformOffsetSizeMode.y) + transformOrigin; + coefficient.coefCA = transformSize * Vector2(transformOffsetSizeMode.z, transformOffsetSizeMode.w) + extraSize; + coefficient.coefCB = coefficient.coefCA * transformAnchorPoint + transformOffset * Vector2(transformOffsetSizeMode.x, transformOffsetSizeMode.y); + } + if(mVisualProperties->mExtendedProperties) + { + const auto decoratedVisualProperties = static_cast(mVisualProperties->mExtendedProperties); + + uint64_t decoratedHash = 0xc70f6907UL; + + decoratedHash = decoratedVisualProperties->mBorderlineWidth.Hash(updateBufferIndex, decoratedHash); + decoratedHash = decoratedVisualProperties->mBorderlineOffset.Hash(updateBufferIndex, decoratedHash); + decoratedHash = decoratedVisualProperties->mBlurRadius.Hash(updateBufferIndex, decoratedHash); + + if(coefficient.decoratedHash != decoratedHash) + { + coefficient.decoratedHash = decoratedHash; + + // DecoratedVisualProperty + const float borderlineWidth = decoratedVisualProperties->mBorderlineWidth.Get(updateBufferIndex); + const float borderlineOffset = decoratedVisualProperties->mBorderlineOffset.Get(updateBufferIndex); + const float blurRadius = decoratedVisualProperties->mBlurRadius.Get(updateBufferIndex); + + DALI_LOG_INFO(gSceneGraphRendererLogFilter, Debug::Verbose, "borderline width %5.3f\n", borderlineWidth); + DALI_LOG_INFO(gSceneGraphRendererLogFilter, Debug::Verbose, "borderline offset %5.3f\n", borderlineOffset); + DALI_LOG_INFO(gSceneGraphRendererLogFilter, Debug::Verbose, "blur radius %5.3f\n", blurRadius); + + // D coefficients be used only decoratedVisual. + // It can be calculated parallely with transform. + + coefficient.coefD = std::max((1.0f + Dali::Clamp(borderlineOffset, -1.0f, 1.0f)) * borderlineWidth, 2.0f * blurRadius); + } + } + + // Calculate vertex position by coefficient + // It will reduce the number of operations + + // const Vector2 minVertexPosition = (XA * -0.5 + XB) * originalSize + (CA * -0.5 + CB) + Vector2(D, D) * -0.5; + // const Vector2 maxVertexPosition = (XA * +0.5 + XB) * originalSize + (CA * +0.5 + CB) + Vector2(D, D) * +0.5; + + // When we set + // basicVertexPosition = XB * originalSize + CB + // scaleVertexPosition = XA * originalSize + CA + D + + // --> minVertexPosition = basicVertexPosition + scaleVertexPosition * -0.5 + // maxVertexPosition = basicVertexPosition + scaleVertexPosition * +0.5 + + // Then, resultSize = 2.0f * max(-minVertexPosition, maxVertexPosition); + // = 2.0f * max(scaleVertexPosition * 0.5 - basicVertexPosition, scaleVertexPosition * 0.5 + basicVertexPosition) + // = scaleVertexPosition + 2.0f * abs(basicVertexPosition) + // Cause transform matrix will think center of vertex is (0, 0) + + const Vector2 originalXY = Vector2(originalUpdateArea.x, originalUpdateArea.y); + const Vector2 originalWH = Vector2(originalUpdateArea.z, originalUpdateArea.w); + + const Vector2 basicVertexPosition = coefficient.coefXB * originalWH + coefficient.coefCB; + const Vector2 scaleVertexPosition = coefficient.coefXA * originalWH + coefficient.coefCA; + + // TODO : We need to re-generate coefficient to consitder area width/height + const Vector4 resultArea = Vector4(originalXY.x, + originalXY.y, + scaleVertexPosition.x + 2.0f * abs(basicVertexPosition.x) + coefficient.coefD, + scaleVertexPosition.y + 2.0f * abs(basicVertexPosition.y) + coefficient.coefD); + + DALI_LOG_INFO(gSceneGraphRendererLogFilter, Debug::Verbose, "%f %f %f %f--> %f %f %f %f\n", originalUpdateArea.x, originalUpdateArea.y, originalUpdateArea.z, originalUpdateArea.w, resultArea.x, resultArea.y, resultArea.z, resultArea.w); + + return resultArea; + } + return originalUpdateArea; } } // namespace SceneGraph