/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include <dali/internal/update/nodes/node.h>
#include <dali/internal/update/rendering/scene-graph-texture-set.h>
+#include <dali/integration-api/debug.h>
+
namespace Dali
{
namespace Internal
{
namespace // unnamed namespace
{
-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<Renderer> gRendererMemoryPool;
+#ifdef DEBUG_ENABLED
+Debug::Filter* gSceneGraphRendererLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_SG_RENDERER");
+#endif
-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<Renderer>& 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(); i < count; ++i)
- {
- bool found = false;
-
- for(CollectedUniformMap::Iterator iter = localMap.Begin(); iter != localMap.End(); ++iter)
- {
- const UniformPropertyMapping& map = (*iter);
- if(map.uniformName == uniformMap[i].uniformName)
- {
- found = true;
- break;
- }
- }
- if(!found)
- {
- 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<Renderer> gRendererMemoryPool;
+ return gRendererMemoryPool;
}
// Flags for re-sending data to renderer.
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<Renderer*>(ptr));
+ new(ptr) Renderer();
+ return RendererKey(key);
}
Renderer::Renderer()
: mSceneController(nullptr),
- mRenderer(nullptr),
+ mRenderer{},
mTextureSet(nullptr),
mGeometry(nullptr),
mShader(nullptr),
mIndexedDrawFirstElement(0u),
mIndexedDrawElementsCount(0u),
mBlendBitmask(0u),
- mRegenerateUniformMap(0u),
mResendFlag(0u),
mDepthFunction(DepthFunction::LESS),
mFaceCullingMode(FaceCullingMode::NONE),
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)
{
- mUniformMapChanged[0] = false;
- mUniformMapChanged[1] = false;
-
- // Observe our own PropertyOwner's uniform map
- AddUniformMapObserver(*this);
}
Renderer::~Renderer()
{
- if(mTextureSet)
- {
- mTextureSet = nullptr;
- }
- if(mShader)
- {
- mShader->RemoveConnectionObserver(*this);
- mShader = nullptr;
- }
}
void Renderer::operator delete(void* ptr)
{
- gRendererMemoryPool.FreeThreadSafe(static_cast<Renderer*>(ptr));
+ GetRendererMemoryPool().FreeThreadSafe(static_cast<Renderer*>(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.Clear();
-
- const UniformMap& rendererUniformMap = PropertyOwner::GetUniformMap();
-
- auto size = rendererUniformMap.Count();
- if(mShader)
- {
- size += mShader->GetUniformMap().Count();
- }
-
- localMap.Reserve(size);
-
- 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*>(&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 || mRenderingBehavior == DevelRenderer::Rendering::CONTINUOUSLY;
+ 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<Renderer::Decay>(static_cast<int>(mUpdateDecay) - 1);
+ }
if(mResendFlag != 0)
{
+ 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);
+ new(slot) DerivedType(rendererPtr, &Render::Renderer::SetGeometry, mGeometry);
}
if(mResendFlag & RESEND_DRAW_COMMANDS)
{
using DerivedType = MessageValue2<Render::Renderer, Dali::DevelRenderer::DrawCommand*, uint32_t>;
uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot(updateBufferIndex, sizeof(DerivedType));
- new(slot) DerivedType(mRenderer, &Render::Renderer::SetDrawCommands, mDrawCommands.data(), mDrawCommands.size());
+ new(slot) DerivedType(rendererPtr, &Render::Renderer::SetDrawCommands, mDrawCommands.data(), mDrawCommands.size());
}
if(mResendFlag & RESEND_FACE_CULLING_MODE)
{
using DerivedType = MessageValue1<Render::Renderer, FaceCullingMode::Type>;
uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot(updateBufferIndex, sizeof(DerivedType));
- new(slot) DerivedType(mRenderer, &Render::Renderer::SetFaceCullingMode, mFaceCullingMode);
+ new(slot) DerivedType(rendererPtr, &Render::Renderer::SetFaceCullingMode, mFaceCullingMode);
}
if(mResendFlag & RESEND_BLEND_BIT_MASK)
{
using DerivedType = MessageValue1<Render::Renderer, uint32_t>;
uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot(updateBufferIndex, sizeof(DerivedType));
- new(slot) DerivedType(mRenderer, &Render::Renderer::SetBlendingBitMask, mBlendBitmask);
+ new(slot) DerivedType(rendererPtr, &Render::Renderer::SetBlendingBitMask, mBlendBitmask);
}
if(mResendFlag & RESEND_BLEND_COLOR)
{
using DerivedType = MessageValue1<Render::Renderer, Vector4>;
uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot(updateBufferIndex, sizeof(DerivedType));
- new(slot) DerivedType(mRenderer, &Render::Renderer::SetBlendColor, GetBlendColor());
+ new(slot) DerivedType(rendererPtr, &Render::Renderer::SetBlendColor, GetBlendColor());
}
if(mResendFlag & RESEND_PREMULTIPLIED_ALPHA)
{
using DerivedType = MessageValue1<Render::Renderer, bool>;
uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot(updateBufferIndex, sizeof(DerivedType));
- new(slot) DerivedType(mRenderer, &Render::Renderer::EnablePreMultipliedAlpha, mPremultipledAlphaEnabled);
+ new(slot) DerivedType(rendererPtr, &Render::Renderer::EnablePreMultipliedAlpha, mPremultipledAlphaEnabled);
}
if(mResendFlag & RESEND_INDEXED_DRAW_FIRST_ELEMENT)
{
using DerivedType = MessageValue1<Render::Renderer, uint32_t>;
uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot(updateBufferIndex, sizeof(DerivedType));
- new(slot) DerivedType(mRenderer, &Render::Renderer::SetIndexedDrawFirstElement, mIndexedDrawFirstElement);
+ new(slot) DerivedType(rendererPtr, &Render::Renderer::SetIndexedDrawFirstElement, mIndexedDrawFirstElement);
}
if(mResendFlag & RESEND_INDEXED_DRAW_ELEMENTS_COUNT)
{
using DerivedType = MessageValue1<Render::Renderer, uint32_t>;
uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot(updateBufferIndex, sizeof(DerivedType));
- new(slot) DerivedType(mRenderer, &Render::Renderer::SetIndexedDrawElementsCount, mIndexedDrawElementsCount);
+ new(slot) DerivedType(rendererPtr, &Render::Renderer::SetIndexedDrawElementsCount, mIndexedDrawElementsCount);
}
if(mResendFlag & RESEND_DEPTH_WRITE_MODE)
{
using DerivedType = MessageValue1<Render::Renderer, DepthWriteMode::Type>;
uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot(updateBufferIndex, sizeof(DerivedType));
- new(slot) DerivedType(mRenderer, &Render::Renderer::SetDepthWriteMode, mDepthWriteMode);
+ new(slot) DerivedType(rendererPtr, &Render::Renderer::SetDepthWriteMode, mDepthWriteMode);
}
if(mResendFlag & RESEND_DEPTH_TEST_MODE)
{
using DerivedType = MessageValue1<Render::Renderer, DepthTestMode::Type>;
uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot(updateBufferIndex, sizeof(DerivedType));
- new(slot) DerivedType(mRenderer, &Render::Renderer::SetDepthTestMode, mDepthTestMode);
+ new(slot) DerivedType(rendererPtr, &Render::Renderer::SetDepthTestMode, mDepthTestMode);
}
if(mResendFlag & RESEND_DEPTH_FUNCTION)
{
using DerivedType = MessageValue1<Render::Renderer, DepthFunction::Type>;
uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot(updateBufferIndex, sizeof(DerivedType));
- new(slot) DerivedType(mRenderer, &Render::Renderer::SetDepthFunction, mDepthFunction);
+ new(slot) DerivedType(rendererPtr, &Render::Renderer::SetDepthFunction, mDepthFunction);
}
if(mResendFlag & RESEND_RENDER_MODE)
{
using DerivedType = MessageValue1<Render::Renderer, RenderMode::Type>;
uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot(updateBufferIndex, sizeof(DerivedType));
- new(slot) DerivedType(mRenderer, &Render::Renderer::SetRenderMode, mStencilParameters.renderMode);
+ new(slot) DerivedType(rendererPtr, &Render::Renderer::SetRenderMode, mStencilParameters.renderMode);
}
if(mResendFlag & RESEND_STENCIL_FUNCTION)
{
using DerivedType = MessageValue1<Render::Renderer, StencilFunction::Type>;
uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot(updateBufferIndex, sizeof(DerivedType));
- new(slot) DerivedType(mRenderer, &Render::Renderer::SetStencilFunction, mStencilParameters.stencilFunction);
+ new(slot) DerivedType(rendererPtr, &Render::Renderer::SetStencilFunction, mStencilParameters.stencilFunction);
}
if(mResendFlag & RESEND_STENCIL_FUNCTION_MASK)
{
using DerivedType = MessageValue1<Render::Renderer, int>;
uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot(updateBufferIndex, sizeof(DerivedType));
- new(slot) DerivedType(mRenderer, &Render::Renderer::SetStencilFunctionMask, mStencilParameters.stencilFunctionMask);
+ new(slot) DerivedType(rendererPtr, &Render::Renderer::SetStencilFunctionMask, mStencilParameters.stencilFunctionMask);
}
if(mResendFlag & RESEND_STENCIL_FUNCTION_REFERENCE)
{
using DerivedType = MessageValue1<Render::Renderer, int>;
uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot(updateBufferIndex, sizeof(DerivedType));
- new(slot) DerivedType(mRenderer, &Render::Renderer::SetStencilFunctionReference, mStencilParameters.stencilFunctionReference);
+ new(slot) DerivedType(rendererPtr, &Render::Renderer::SetStencilFunctionReference, mStencilParameters.stencilFunctionReference);
}
if(mResendFlag & RESEND_STENCIL_MASK)
{
using DerivedType = MessageValue1<Render::Renderer, int>;
uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot(updateBufferIndex, sizeof(DerivedType));
- new(slot) DerivedType(mRenderer, &Render::Renderer::SetStencilMask, mStencilParameters.stencilMask);
+ new(slot) DerivedType(rendererPtr, &Render::Renderer::SetStencilMask, mStencilParameters.stencilMask);
}
if(mResendFlag & RESEND_STENCIL_OPERATION_ON_FAIL)
{
using DerivedType = MessageValue1<Render::Renderer, StencilOperation::Type>;
uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot(updateBufferIndex, sizeof(DerivedType));
- new(slot) DerivedType(mRenderer, &Render::Renderer::SetStencilOperationOnFail, mStencilParameters.stencilOperationOnFail);
+ new(slot) DerivedType(rendererPtr, &Render::Renderer::SetStencilOperationOnFail, mStencilParameters.stencilOperationOnFail);
}
if(mResendFlag & RESEND_STENCIL_OPERATION_ON_Z_FAIL)
{
using DerivedType = MessageValue1<Render::Renderer, StencilOperation::Type>;
uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot(updateBufferIndex, sizeof(DerivedType));
- new(slot) DerivedType(mRenderer, &Render::Renderer::SetStencilOperationOnZFail, mStencilParameters.stencilOperationOnZFail);
+ new(slot) DerivedType(rendererPtr, &Render::Renderer::SetStencilOperationOnZFail, mStencilParameters.stencilOperationOnZFail);
}
if(mResendFlag & RESEND_STENCIL_OPERATION_ON_Z_PASS)
{
using DerivedType = MessageValue1<Render::Renderer, StencilOperation::Type>;
uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot(updateBufferIndex, sizeof(DerivedType));
- new(slot) DerivedType(mRenderer, &Render::Renderer::SetStencilOperationOnZPass, mStencilParameters.stencilOperationOnZPass);
+ new(slot) DerivedType(rendererPtr, &Render::Renderer::SetStencilOperationOnZPass, mStencilParameters.stencilOperationOnZPass);
}
if(mResendFlag & RESEND_SHADER)
{
using DerivedType = MessageValue1<Render::Renderer, bool>;
uint32_t* slot = mSceneController->GetRenderQueue().ReserveMessageSlot(updateBufferIndex, sizeof(DerivedType));
- new(slot) DerivedType(mRenderer, &Render::Renderer::SetShaderChanged, true);
+ new(slot) DerivedType(rendererPtr, &Render::Renderer::SetShaderChanged, true);
}
+ if(mResendFlag & RESEND_SET_RENDER_CALLBACK)
+ {
+ using DerivedType = MessageValue1<Render::Renderer, Dali::RenderCallback*>;
+ 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;
}
{
DALI_ASSERT_DEBUG(textureSet != NULL && "Texture set pointer is NULL");
- mTextureSet = textureSet;
- mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
+ mTextureSet = textureSet;
+
+ mDirtyFlag = true;
+ SetUpdated(true);
}
-const Vector<Render::Texture*>* Renderer::GetTextures() const
+const Vector<Render::TextureKey>* Renderer::GetTextures() const
{
return mTextureSet ? &(mTextureSet->GetTextures()) : nullptr;
}
{
DALI_ASSERT_DEBUG(shader != NULL && "Shader pointer is NULL");
- if(mShader)
- {
- mShader->RemoveConnectionObserver(*this);
- }
-
- mShader = shader;
- mShader->AddConnectionObserver(*this);
- mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
+ mShader = shader;
+ mShaderMapChangeCounter = 0u;
+ mRegenerateUniformMap = true;
mResendFlag |= RESEND_GEOMETRY | RESEND_SHADER;
+ mDirtyFlag = true;
}
void Renderer::SetGeometry(Render::Geometry* geometry)
void Renderer::SetDepthIndex(int depthIndex)
{
mDepthIndex = depthIndex;
+
+ mDirtyFlag = true;
+ SetUpdated(true);
}
void Renderer::SetFaceCullingMode(FaceCullingMode::Type faceCullingMode)
void Renderer::SetBlendMode(BlendMode::Type blendingMode)
{
mBlendMode = blendingMode;
+
+ mDirtyFlag = true;
+ SetUpdated(true);
}
BlendMode::Type Renderer::GetBlendMode() const
{
mBlendBitmask = options;
mResendFlag |= RESEND_BLEND_BIT_MASK;
+ mDirtyFlag = true;
}
}
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)
{
mOpacity.Bake(updateBufferIndex, opacity);
+
+ mDirtyFlag = true;
+ SetUpdated(true);
}
float Renderer::GetOpacity(BufferIndex updateBufferIndex) const
void Renderer::SetRenderingBehavior(DevelRenderer::Rendering::Type renderingBehavior)
{
mRenderingBehavior = renderingBehavior;
+ SetUpdated(true);
}
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 )
+// 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;
+ mRegenerateUniformMap = true;
mSceneController = &sceneController;
- mRenderer = Render::Renderer::New(this, mGeometry, mBlendBitmask, GetBlendColor(), static_cast<FaceCullingMode::Type>(mFaceCullingMode), mPremultipledAlphaEnabled, mDepthWriteMode, mDepthTestMode, mDepthFunction, mStencilParameters);
+ mRenderer = Render::Renderer::NewKey(this, mGeometry, mBlendBitmask, GetBlendColor(), static_cast<FaceCullingMode::Type>(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 )
+// 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
+ // Remove renderer from RenderManager
if(mRenderer)
{
- mSceneController->GetRenderMessageDispatcher().RemoveRenderer(*mRenderer);
- mRenderer = nullptr;
+ mSceneController->GetRenderMessageDispatcher().RemoveRenderer(mRenderer);
+ mRenderer = Render::RendererKey{};
}
mSceneController = nullptr;
}
-Render::Renderer& Renderer::GetRenderer()
+Render::RendererKey Renderer::GetRenderer()
{
- return *mRenderer;
-}
-
-const CollectedUniformMap& Renderer::GetUniformMap(BufferIndex bufferIndex) const
-{
- return mCollectedUniformMap[bufferIndex];
+ return mRenderer;
}
Renderer::OpacityType Renderer::GetOpacityType(BufferIndex updateBufferIndex, const Node& node) const
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];
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:
{
return opacityType;
}
-void Renderer::ConnectionsChanged(PropertyOwner& object)
+void Renderer::UpdateUniformMap(BufferIndex updateBufferIndex)
{
- // One of our child objects has changed it's connections. Ensure the uniform
- // map gets regenerated during PrepareRender
- mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
-}
+ if(mRegenerateUniformMap)
+ {
+ CollectedUniformMap& localMap = mCollectedUniformMap;
+ localMap.Clear();
-void Renderer::ConnectedUniformMapChanged()
-{
- mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
-}
+ const UniformMap& rendererUniformMap = PropertyOwner::GetUniformMap();
-void Renderer::UniformMappingsChanged(const UniformMap& mappings)
-{
- // The mappings are either from PropertyOwner base class, or the Actor
- mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
-}
+ auto size = rendererUniformMap.Count();
+ if(mShader)
+ {
+ size += mShader->GetUniformMap().Count();
+ }
-void Renderer::ObservedObjectDestroyed(PropertyOwner& owner)
-{
- if(reinterpret_cast<PropertyOwner*>(mShader) == &owner)
+ localMap.Reserve(size);
+ localMap.AddMappings(rendererUniformMap);
+ if(mShader)
+ {
+ localMap.AddMappings(mShader->GetUniformMap());
+ }
+ localMap.UpdateChangeCounter();
+
+ mRegenerateUniformMap = false;
+ SetUpdated(true);
+ }
+
+ uint64_t hash = 0xc70f6907UL;
+ const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = GetUniformMapDataProvider();
+ const SceneGraph::CollectedUniformMap& collectedUniformMap = uniformMapDataProvider.GetCollectedUniformMap();
+ for(uint32_t i = 0u, count = collectedUniformMap.Count(); i < count; ++i)
+ {
+ hash = collectedUniformMap.mUniformMap[i].propertyPtr->Hash(updateBufferIndex, hash);
+ }
+ if(mUniformsHash != hash)
{
- mShader = nullptr;
+ mUniformsHash = hash;
+ SetUpdated(true);
}
}
mResendFlag |= RESEND_DRAW_COMMANDS;
}
+bool Renderer::IsDirty() const
+{
+ // Check whether the opacity property has changed
+ return (mDirtyFlag || !mOpacity.IsClean());
+}
+
+void Renderer::ResetDirtyFlag()
+{
+ mDirtyFlag = false;
+
+ SetUpdated(false);
+}
+
+uint32_t Renderer::GetMemoryPoolCapacity()
+{
+ return GetRendererMemoryPool().GetCapacity();
+}
+
+void Renderer::OnMappingChanged()
+{
+ // Properties have been registered on the base class.
+ mRegenerateUniformMap = true; // Should remain true until this renderer is added to a RenderList.
+}
+
+const CollectedUniformMap& Renderer::GetCollectedUniformMap() const
+{
+ return mCollectedUniformMap;
+}
+
+Vector4 Renderer::GetVisualTransformedUpdateArea(BufferIndex updateBufferIndex, const Vector4& originalUpdateArea) noexcept
+{
+ 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<VisualRenderer::AnimatableDecoratedVisualProperties*>(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
} // namespace Internal
} // namespace Dali