X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Finternal%2Frender%2Frenderers%2Frender-renderer.cpp;h=7a19c6b77072a021ca7e0e34f2a7b1650e1ca49d;hb=068c5d3906ac2acb845c09e339dfe346bbea89e2;hp=518c1dea0bca0c811760ebb2c4fd318e6ff9b35a;hpb=b192f4f14bad2da813b76387b6abc35411246be4;p=platform%2Fcore%2Fuifw%2Fdali-core.git diff --git a/dali/internal/render/renderers/render-renderer.cpp b/dali/internal/render/renderers/render-renderer.cpp index 518c1de..7a19c6b 100644 --- a/dali/internal/render/renderers/render-renderer.cpp +++ b/dali/internal/render/renderers/render-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. @@ -19,427 +19,331 @@ #include // INTERNAL INCLUDES +#include +#include #include -#include -#include -#include -#include +#include +#include +#include +#include #include #include -#include - -namespace Dali -{ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include -namespace Internal +namespace Dali::Internal { - namespace { - +// Helper to get the property value getter by type +typedef const float& (PropertyInputImpl::*FuncGetter)(BufferIndex) const; +constexpr FuncGetter GetPropertyValueGetter(Property::Type type) +{ + switch(type) + { + case Property::BOOLEAN: + { + return FuncGetter(&PropertyInputImpl::GetBoolean); + } + case Property::INTEGER: + { + return FuncGetter(&PropertyInputImpl::GetInteger); + } + case Property::FLOAT: + { + return FuncGetter(&PropertyInputImpl::GetFloat); + } + case Property::VECTOR2: + { + return FuncGetter(&PropertyInputImpl::GetVector2); + } + case Property::VECTOR3: + { + return FuncGetter(&PropertyInputImpl::GetVector3); + } + case Property::VECTOR4: + { + return FuncGetter(&PropertyInputImpl::GetVector4); + } + case Property::MATRIX3: + { + return FuncGetter(&PropertyInputImpl::GetMatrix3); + } + case Property::MATRIX: + { + return FuncGetter(&PropertyInputImpl::GetMatrix); + } + default: + { + return nullptr; + } + } +} /** - * Helper to set view and projection matrices once per program - * @param program to set the matrices to - * @param modelMatrix to set - * @param viewMatrix to set - * @param projectionMatrix to set - * @param modelViewMatrix to set - * @param modelViewProjectionMatrix to set + * Helper function that returns size of uniform datatypes based + * on property type. */ -inline void SetMatrices( Program& program, - const Matrix& modelMatrix, - const Matrix& viewMatrix, - const Matrix& projectionMatrix, - const Matrix& modelViewMatrix ) -{ - GLint loc = program.GetUniformLocation( Program::UNIFORM_MODEL_MATRIX ); - if( Program::UNIFORM_UNKNOWN != loc ) - { - program.SetUniformMatrix4fv( loc, 1, modelMatrix.AsFloat() ); - } - loc = program.GetUniformLocation( Program::UNIFORM_VIEW_MATRIX ); - if( Program::UNIFORM_UNKNOWN != loc ) +constexpr int GetPropertyValueSizeForUniform(Property::Type type) +{ + switch(type) { - if( program.GetViewMatrix() != &viewMatrix ) + case Property::Type::BOOLEAN: { - program.SetViewMatrix( &viewMatrix ); - program.SetUniformMatrix4fv( loc, 1, viewMatrix.AsFloat() ); + return sizeof(bool); } - } - // set projection matrix if program has not yet received it this frame or if it is dirty - loc = program.GetUniformLocation( Program::UNIFORM_PROJECTION_MATRIX ); - if( Program::UNIFORM_UNKNOWN != loc ) - { - if( program.GetProjectionMatrix() != &projectionMatrix ) + case Property::Type::FLOAT: { - program.SetProjectionMatrix( &projectionMatrix ); - program.SetUniformMatrix4fv( loc, 1, projectionMatrix.AsFloat() ); + return sizeof(float); } - } - loc = program.GetUniformLocation(Program::UNIFORM_MODELVIEW_MATRIX); - if( Program::UNIFORM_UNKNOWN != loc ) - { - program.SetUniformMatrix4fv( loc, 1, modelViewMatrix.AsFloat() ); - } + case Property::Type::INTEGER: + { + return sizeof(int); + } + case Property::Type::VECTOR2: + { + return sizeof(Vector2); + } + case Property::Type::VECTOR3: + { + return sizeof(Vector3); + } + case Property::Type::VECTOR4: + { + return sizeof(Vector4); + } + case Property::Type::MATRIX3: + { + return sizeof(Matrix3); + } + case Property::Type::MATRIX: + { + return sizeof(Matrix); + } + default: + { + return 0; + } + }; +} - loc = program.GetUniformLocation( Program::UNIFORM_MVP_MATRIX ); - if( Program::UNIFORM_UNKNOWN != loc ) - { - Matrix modelViewProjectionMatrix(false); - Matrix::Multiply( modelViewProjectionMatrix, modelViewMatrix, projectionMatrix ); - program.SetUniformMatrix4fv( loc, 1, modelViewProjectionMatrix.AsFloat() ); - } +/** + * Helper function to calculate the correct alignment of data for uniform buffers + * @param dataSize size of uniform buffer + * @return aligned offset of data + */ +inline uint32_t GetUniformBufferDataAlignment(uint32_t dataSize) +{ + return ((dataSize / 256u) + ((dataSize % 256u) ? 1u : 0u)) * 256u; +} - loc = program.GetUniformLocation( Program::UNIFORM_NORMAL_MATRIX ); - if( Program::UNIFORM_UNKNOWN != loc ) +/** + * @brief Store latest bound RenderGeometry, and help that we can skip duplicated vertex attributes bind. + * + * @param[in] geometry Current geometry to be used, or nullptr if render finished + * @return True if we can reuse latest bound vertex attributes. False otherwise. + */ +inline bool ReuseLatestBoundVertexAttributes(const Render::Geometry* geometry) +{ + static const Render::Geometry* gLatestVertexBoundGeometry = nullptr; + if(gLatestVertexBoundGeometry == geometry) { - Matrix3 normalMatrix; - normalMatrix = modelViewMatrix; - normalMatrix.Invert(); - normalMatrix.Transpose(); - program.SetUniformMatrix3fv( loc, 1, normalMatrix.AsFloat() ); + return true; } + gLatestVertexBoundGeometry = geometry; + return false; } -} +} // namespace namespace Render { +namespace +{ +MemoryPoolObjectAllocator gRenderRendererMemoryPool; +} -Renderer* Renderer::New( SceneGraph::RenderDataProvider* dataProvider, - Render::Geometry* geometry, - uint32_t blendingBitmask, - const Vector4& blendColor, - FaceCullingMode::Type faceCullingMode, - bool preMultipliedAlphaEnabled, - DepthWriteMode::Type depthWriteMode, - DepthTestMode::Type depthTestMode, - DepthFunction::Type depthFunction, - StencilParameters& stencilParameters ) -{ - return new Renderer( dataProvider, geometry, blendingBitmask, blendColor, - faceCullingMode, preMultipliedAlphaEnabled, depthWriteMode, depthTestMode, - depthFunction, stencilParameters ); -} - -Renderer::Renderer( SceneGraph::RenderDataProvider* dataProvider, - Render::Geometry* geometry, - uint32_t blendingBitmask, - const Vector4& blendColor, - FaceCullingMode::Type faceCullingMode, - bool preMultipliedAlphaEnabled, - DepthWriteMode::Type depthWriteMode, - DepthTestMode::Type depthTestMode, - DepthFunction::Type depthFunction, - StencilParameters& stencilParameters ) -: mRenderDataProvider( dataProvider ), - mContext( nullptr), - mGeometry( geometry ), - mUniformIndexMap(), - mAttributesLocation(), - mUniformsHash(), - mStencilParameters( stencilParameters ), +void Renderer::PrepareCommandBuffer() +{ + // Reset latest geometry informations, So we can bind the first of geometry. + ReuseLatestBoundVertexAttributes(nullptr); + + // todo : Fill here as many caches as we can store for reduce the number of command buffers +} + +RendererKey Renderer::NewKey(SceneGraph::RenderDataProvider* dataProvider, + Render::Geometry* geometry, + uint32_t blendingBitmask, + const Vector4& blendColor, + FaceCullingMode::Type faceCullingMode, + bool preMultipliedAlphaEnabled, + DepthWriteMode::Type depthWriteMode, + DepthTestMode::Type depthTestMode, + DepthFunction::Type depthFunction, + StencilParameters& stencilParameters) +{ + void* ptr = gRenderRendererMemoryPool.AllocateRawThreadSafe(); + auto key = gRenderRendererMemoryPool.GetKeyFromPtr(static_cast(ptr)); + + // Use placement new to construct renderer. + new(ptr) Renderer(dataProvider, geometry, blendingBitmask, blendColor, faceCullingMode, preMultipliedAlphaEnabled, depthWriteMode, depthTestMode, depthFunction, stencilParameters); + return RendererKey(key); +} + +Renderer::Renderer(SceneGraph::RenderDataProvider* dataProvider, + Render::Geometry* geometry, + uint32_t blendingBitmask, + const Vector4& blendColor, + FaceCullingMode::Type faceCullingMode, + bool preMultipliedAlphaEnabled, + DepthWriteMode::Type depthWriteMode, + DepthTestMode::Type depthTestMode, + DepthFunction::Type depthFunction, + StencilParameters& stencilParameters) +: mGraphicsController(nullptr), + mRenderDataProvider(dataProvider), + mGeometry(geometry), + mProgramCache(nullptr), + mStencilParameters(stencilParameters), mBlendingOptions(), - mIndexedDrawFirstElement( 0 ), - mIndexedDrawElementsCount( 0 ), - mDepthFunction( depthFunction ), - mFaceCullingMode( faceCullingMode ), - mDepthWriteMode( depthWriteMode ), - mDepthTestMode( depthTestMode ), - mUpdateAttributesLocation( true ), - mPremultipledAlphaEnabled( preMultipliedAlphaEnabled ), - mShaderChanged( false ), - mUpdated( true ) -{ - if( blendingBitmask != 0u ) + mIndexedDrawFirstElement(0), + mIndexedDrawElementsCount(0), + mDepthFunction(depthFunction), + mFaceCullingMode(faceCullingMode), + mDepthWriteMode(depthWriteMode), + mDepthTestMode(depthTestMode), + mPremultipliedAlphaEnabled(preMultipliedAlphaEnabled), + mShaderChanged(false) +{ + if(blendingBitmask != 0u) { - mBlendingOptions.SetBitmask( blendingBitmask ); + mBlendingOptions.SetBitmask(blendingBitmask); } - mBlendingOptions.SetBlendColor( blendColor ); + mBlendingOptions.SetBlendColor(blendColor); } -void Renderer::Initialize( Context& context ) +void Renderer::Initialize(Graphics::Controller& graphicsController, ProgramCache& programCache, Render::ShaderCache& shaderCache, Render::UniformBufferManager& uniformBufferManager, Render::PipelineCache& pipelineCache) { - mContext = &context; + mGraphicsController = &graphicsController; + mProgramCache = &programCache; + mShaderCache = &shaderCache; + mUniformBufferManager = &uniformBufferManager; + mPipelineCache = &pipelineCache; } Renderer::~Renderer() = default; -void Renderer::SetGeometry( Render::Geometry* geometry ) +void Renderer::operator delete(void* ptr) { - mGeometry = geometry; - mUpdateAttributesLocation = true; -} -void Renderer::SetDrawCommands( Dali::DevelRenderer::DrawCommand* pDrawCommands, uint32_t size ) -{ - mDrawCommands.clear(); - mDrawCommands.insert( mDrawCommands.end(), pDrawCommands, pDrawCommands+size ); + gRenderRendererMemoryPool.FreeThreadSafe(static_cast(ptr)); } -void Renderer::SetBlending( Context& context, bool blend ) +Renderer* Renderer::Get(RendererKey::KeyType rendererKey) { - context.SetBlend( blend ); - if( blend ) - { - // Blend color is optional and rarely used - const Vector4* blendColor = mBlendingOptions.GetBlendColor(); - if( blendColor ) - { - context.SetCustomBlendColor( *blendColor ); - } - else - { - context.SetDefaultBlendColor(); - } - - // Set blend source & destination factors - context.BlendFuncSeparate( mBlendingOptions.GetBlendSrcFactorRgb(), - mBlendingOptions.GetBlendDestFactorRgb(), - mBlendingOptions.GetBlendSrcFactorAlpha(), - mBlendingOptions.GetBlendDestFactorAlpha() ); - - // Set blend equations - Dali::DevelBlendEquation::Type rgbEquation = mBlendingOptions.GetBlendEquationRgb(); - Dali::DevelBlendEquation::Type alphaEquation = mBlendingOptions.GetBlendEquationAlpha(); - - if( mBlendingOptions.IsAdvancedBlendEquationApplied() && mPremultipledAlphaEnabled ) - { - if( rgbEquation != alphaEquation ) - { - DALI_LOG_ERROR( "Advanced Blend Equation have to be appried by using BlendEquation.\n" ); - } - context.BlendEquation( rgbEquation ); - } - else - { - context.BlendEquationSeparate( rgbEquation, alphaEquation ); - } - } - - mUpdated = true; + return gRenderRendererMemoryPool.GetPtrFromKey(rendererKey); } -void Renderer::GlContextDestroyed() +void Renderer::SetGeometry(Render::Geometry* geometry) { - mGeometry->GlContextDestroyed(); + mGeometry = geometry; } -void Renderer::GlCleanup() +void Renderer::SetDrawCommands(Dali::DevelRenderer::DrawCommand* pDrawCommands, uint32_t size) { + mDrawCommands.clear(); + mDrawCommands.insert(mDrawCommands.end(), pDrawCommands, pDrawCommands + size); } -void Renderer::SetUniforms( BufferIndex bufferIndex, const SceneGraph::NodeDataProvider& node, const Vector3& size, Program& program ) +void Renderer::BindTextures(Graphics::CommandBuffer& commandBuffer, Vector& boundTextures) { - // Check if the map has changed - DALI_ASSERT_DEBUG( mRenderDataProvider && "No Uniform map data provider available" ); - - const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap(); - - if( uniformMapDataProvider.GetUniformMapChanged( bufferIndex ) || - node.GetUniformMapChanged(bufferIndex) || - mUniformIndexMap.Count() == 0 || - mShaderChanged ) - { - // Reset shader pointer - mShaderChanged = false; - - const SceneGraph::CollectedUniformMap& uniformMap = uniformMapDataProvider.GetUniformMap( bufferIndex ); - const SceneGraph::CollectedUniformMap& uniformMapNode = node.GetUniformMap( bufferIndex ); - - uint32_t maxMaps = static_cast( uniformMap.Count() + uniformMapNode.Count() ); // 4,294,967,295 maps should be enough - mUniformIndexMap.Clear(); // Clear contents, but keep memory if we don't change size - mUniformIndexMap.Resize( maxMaps ); - - uint32_t mapIndex = 0; - for(; mapIndex < uniformMap.Count() ; ++mapIndex ) - { - mUniformIndexMap[mapIndex].propertyValue = uniformMap[mapIndex].propertyPtr; - mUniformIndexMap[mapIndex].uniformIndex = program.RegisterUniform(uniformMap[mapIndex].uniformName); - } - - for( uint32_t nodeMapIndex = 0; nodeMapIndex < uniformMapNode.Count() ; ++nodeMapIndex ) - { - uint32_t uniformIndex = program.RegisterUniform(uniformMapNode[nodeMapIndex].uniformName); - bool found(false); - for( uint32_t i = 0; iGetTextures()); + auto samplers(mRenderDataProvider->GetSamplers()); - // Set uniforms in local map - for( UniformIndexMappings::Iterator iter = mUniformIndexMap.Begin(), - end = mUniformIndexMap.End() ; - iter != end ; - ++iter ) - { - SetUniformFromProperty( bufferIndex, program, *iter ); - } + std::vector textureBindings; - GLint sizeLoc = program.GetUniformLocation( Program::UNIFORM_SIZE ); - if( -1 != sizeLoc ) + if(textures != nullptr) { - program.SetSizeUniform3f( sizeLoc, size.x, size.y, size.z ); - } -} + const std::uint32_t texturesCount(static_cast(textures->Count())); + textureBindings.reserve(texturesCount); -void Renderer::SetUniformFromProperty( BufferIndex bufferIndex, Program& program, UniformIndexMap& map ) -{ - GLint location = program.GetUniformLocation(map.uniformIndex); - if( Program::UNIFORM_UNKNOWN != location ) - { - // switch based on property type to use correct GL uniform setter - switch ( map.propertyValue->GetType() ) + for(uint32_t i = 0; i < texturesCount; ++i) // not expecting more than uint32_t of textures { - case Property::INTEGER: - { - program.SetUniform1i( location, map.propertyValue->GetInteger( bufferIndex ) ); - break; - } - case Property::FLOAT: - { - program.SetUniform1f( location, map.propertyValue->GetFloat( bufferIndex ) ); - break; - } - case Property::VECTOR2: + if((*textures)[i] && (*textures)[i]->GetGraphicsObject()) { - Vector2 value( map.propertyValue->GetVector2( bufferIndex ) ); - program.SetUniform2f( location, value.x, value.y ); - break; - } + Graphics::Texture* graphicsTexture = (*textures)[i]->GetGraphicsObject(); + // if the sampler exists, + // if it's default, delete the graphics object + // otherwise re-initialize it if dirty - case Property::VECTOR3: - { - Vector3 value( map.propertyValue->GetVector3( bufferIndex ) ); - program.SetUniform3f( location, value.x, value.y, value.z ); - break; - } + const Graphics::Sampler* graphicsSampler = samplers ? ((*samplers)[i] ? (*samplers)[i]->GetGraphicsObject() + : nullptr) + : nullptr; - case Property::VECTOR4: - { - Vector4 value( map.propertyValue->GetVector4( bufferIndex ) ); - program.SetUniform4f( location, value.x, value.y, value.z, value.w ); - break; - } + boundTextures.PushBack(graphicsTexture); + const Graphics::TextureBinding textureBinding{graphicsTexture, graphicsSampler, textureUnit}; + textureBindings.push_back(textureBinding); - case Property::ROTATION: - { - Quaternion value( map.propertyValue->GetQuaternion( bufferIndex ) ); - program.SetUniform4f( location, value.mVector.x, value.mVector.y, value.mVector.z, value.mVector.w ); - break; - } - - case Property::MATRIX: - { - const Matrix& value = map.propertyValue->GetMatrix(bufferIndex); - program.SetUniformMatrix4fv(location, 1, value.AsFloat() ); - break; - } - - case Property::MATRIX3: - { - const Matrix3& value = map.propertyValue->GetMatrix3(bufferIndex); - program.SetUniformMatrix3fv(location, 1, value.AsFloat() ); - break; - } - - default: - { - // Other property types are ignored - break; + ++textureUnit; } } } -} -bool Renderer::BindTextures( Context& context, Program& program, Vector& boundTextures ) -{ - uint32_t textureUnit = 0; - bool result = true; - - GLint uniformLocation(-1); - std::vector& samplers( mRenderDataProvider->GetSamplers() ); - std::vector& textures( mRenderDataProvider->GetTextures() ); - for( uint32_t i = 0; i < static_cast( textures.size() ) && result; ++i ) // not expecting more than uint32_t of textures + if(!textureBindings.empty()) { - if( textures[i] ) - { - result = textures[i]->Bind(context, textureUnit, samplers[i] ); - boundTextures.PushBack( textures[i]->GetId() ); - if( result && program.GetSamplerUniformLocation( i, uniformLocation ) ) - { - program.SetUniform1i( uniformLocation, textureUnit ); - ++textureUnit; - } - } + commandBuffer.BindTextures(textureBindings); } - - return result; } -void Renderer::SetFaceCullingMode( FaceCullingMode::Type mode ) +void Renderer::SetFaceCullingMode(FaceCullingMode::Type mode) { - mFaceCullingMode = mode; - mUpdated = true; + mFaceCullingMode = mode; } -void Renderer::SetBlendingBitMask( uint32_t bitmask ) +void Renderer::SetBlendingBitMask(uint32_t bitmask) { - mBlendingOptions.SetBitmask( bitmask ); - mUpdated = true; + mBlendingOptions.SetBitmask(bitmask); } -void Renderer::SetBlendColor( const Vector4& color ) +void Renderer::SetBlendColor(const Vector4& color) { - mBlendingOptions.SetBlendColor( color ); - mUpdated = true; + mBlendingOptions.SetBlendColor(color); } -void Renderer::SetIndexedDrawFirstElement( uint32_t firstElement ) +void Renderer::SetIndexedDrawFirstElement(uint32_t firstElement) { mIndexedDrawFirstElement = firstElement; - mUpdated = true; } -void Renderer::SetIndexedDrawElementsCount( uint32_t elementsCount ) +void Renderer::SetIndexedDrawElementsCount(uint32_t elementsCount) { mIndexedDrawElementsCount = elementsCount; - mUpdated = true; } -void Renderer::EnablePreMultipliedAlpha( bool enable ) +void Renderer::EnablePreMultipliedAlpha(bool enable) { - mPremultipledAlphaEnabled = enable; - mUpdated = true; + mPremultipliedAlphaEnabled = enable; } -void Renderer::SetDepthWriteMode( DepthWriteMode::Type depthWriteMode ) +void Renderer::SetDepthWriteMode(DepthWriteMode::Type depthWriteMode) { mDepthWriteMode = depthWriteMode; - mUpdated = true; } -void Renderer::SetDepthTestMode( DepthTestMode::Type depthTestMode ) +void Renderer::SetDepthTestMode(DepthTestMode::Type depthTestMode) { mDepthTestMode = depthTestMode; - mUpdated = true; } DepthWriteMode::Type Renderer::GetDepthWriteMode() const @@ -452,10 +356,9 @@ DepthTestMode::Type Renderer::GetDepthTestMode() const return mDepthTestMode; } -void Renderer::SetDepthFunction( DepthFunction::Type depthFunction ) +void Renderer::SetDepthFunction(DepthFunction::Type depthFunction) { mDepthFunction = depthFunction; - mUpdated = true; } DepthFunction::Type Renderer::GetDepthFunction() const @@ -463,10 +366,9 @@ DepthFunction::Type Renderer::GetDepthFunction() const return mDepthFunction; } -void Renderer::SetRenderMode( RenderMode::Type renderMode ) +void Renderer::SetRenderMode(RenderMode::Type renderMode) { mStencilParameters.renderMode = renderMode; - mUpdated = true; } RenderMode::Type Renderer::GetRenderMode() const @@ -474,10 +376,9 @@ RenderMode::Type Renderer::GetRenderMode() const return mStencilParameters.renderMode; } -void Renderer::SetStencilFunction( StencilFunction::Type stencilFunction ) +void Renderer::SetStencilFunction(StencilFunction::Type stencilFunction) { mStencilParameters.stencilFunction = stencilFunction; - mUpdated = true; } StencilFunction::Type Renderer::GetStencilFunction() const @@ -485,10 +386,9 @@ StencilFunction::Type Renderer::GetStencilFunction() const return mStencilParameters.stencilFunction; } -void Renderer::SetStencilFunctionMask( int stencilFunctionMask ) +void Renderer::SetStencilFunctionMask(int stencilFunctionMask) { mStencilParameters.stencilFunctionMask = stencilFunctionMask; - mUpdated = true; } int Renderer::GetStencilFunctionMask() const @@ -496,10 +396,9 @@ int Renderer::GetStencilFunctionMask() const return mStencilParameters.stencilFunctionMask; } -void Renderer::SetStencilFunctionReference( int stencilFunctionReference ) +void Renderer::SetStencilFunctionReference(int stencilFunctionReference) { mStencilParameters.stencilFunctionReference = stencilFunctionReference; - mUpdated = true; } int Renderer::GetStencilFunctionReference() const @@ -507,10 +406,9 @@ int Renderer::GetStencilFunctionReference() const return mStencilParameters.stencilFunctionReference; } -void Renderer::SetStencilMask( int stencilMask ) +void Renderer::SetStencilMask(int stencilMask) { mStencilParameters.stencilMask = stencilMask; - mUpdated = true; } int Renderer::GetStencilMask() const @@ -518,10 +416,9 @@ int Renderer::GetStencilMask() const return mStencilParameters.stencilMask; } -void Renderer::SetStencilOperationOnFail( StencilOperation::Type stencilOperationOnFail ) +void Renderer::SetStencilOperationOnFail(StencilOperation::Type stencilOperationOnFail) { mStencilParameters.stencilOperationOnFail = stencilOperationOnFail; - mUpdated = true; } StencilOperation::Type Renderer::GetStencilOperationOnFail() const @@ -529,10 +426,9 @@ StencilOperation::Type Renderer::GetStencilOperationOnFail() const return mStencilParameters.stencilOperationOnFail; } -void Renderer::SetStencilOperationOnZFail( StencilOperation::Type stencilOperationOnZFail ) +void Renderer::SetStencilOperationOnZFail(StencilOperation::Type stencilOperationOnZFail) { mStencilParameters.stencilOperationOnZFail = stencilOperationOnZFail; - mUpdated = true; } StencilOperation::Type Renderer::GetStencilOperationOnZFail() const @@ -540,10 +436,9 @@ StencilOperation::Type Renderer::GetStencilOperationOnZFail() const return mStencilParameters.stencilOperationOnZFail; } -void Renderer::SetStencilOperationOnZPass( StencilOperation::Type stencilOperationOnZPass ) +void Renderer::SetStencilOperationOnZPass(StencilOperation::Type stencilOperationOnZPass) { mStencilParameters.stencilOperationOnZPass = stencilOperationOnZPass; - mUpdated = true; } StencilOperation::Type Renderer::GetStencilOperationOnZPass() const @@ -551,207 +446,535 @@ StencilOperation::Type Renderer::GetStencilOperationOnZPass() const return mStencilParameters.stencilOperationOnZPass; } -void Renderer::Upload( Context& context ) +void Renderer::Upload() { - mGeometry->Upload( context ); + mGeometry->Upload(*mGraphicsController); } -void Renderer::Render( Context& context, - BufferIndex bufferIndex, - const SceneGraph::NodeDataProvider& node, - const Matrix& modelMatrix, - const Matrix& modelViewMatrix, - const Matrix& viewMatrix, - const Matrix& projectionMatrix, - const Vector3& size, - bool blend, - Vector& boundTextures, - const Dali::Internal::SceneGraph::RenderInstruction& instruction, - uint32_t queueIndex ) +bool Renderer::Render(Graphics::CommandBuffer& commandBuffer, + BufferIndex bufferIndex, + const SceneGraph::NodeDataProvider& node, + const Matrix& modelMatrix, + const Matrix& modelViewMatrix, + const Matrix& viewMatrix, + const Matrix& projectionMatrix, + const Vector3& size, + bool blend, + Vector& boundTextures, + const Dali::Internal::SceneGraph::RenderInstruction& instruction, + uint32_t queueIndex) { // Before doing anything test if the call happens in the right queue - if( mDrawCommands.empty() && queueIndex > 0 ) + if(mDrawCommands.empty() && queueIndex > 0) { - return; + return false; + } + + // Check if there is render callback + if(mRenderCallback) + { + if(!mRenderCallbackInput) + { + mRenderCallbackInput = std::unique_ptr(new RenderCallbackInput); + } + + Graphics::DrawNativeInfo info{}; + info.api = Graphics::DrawNativeAPI::GLES; + info.callback = &static_cast(*mRenderCallback); + info.userData = mRenderCallbackInput.get(); + + // Set storage for the context to be used + info.glesNativeInfo.eglSharedContextStoragePointer = &mRenderCallbackInput->eglContext; + info.reserved = nullptr; + + auto& textureResources = mRenderCallback->GetTextureResources(); + + if(!textureResources.empty()) + { + mRenderCallbackTextureBindings.clear(); + mRenderCallbackInput->textureBindings.resize(textureResources.size()); + auto i = 0u; + for(auto& texture : textureResources) + { + auto& textureImpl = GetImplementation(texture); + auto graphicsTexture = textureImpl.GetRenderTextureKey()->GetGraphicsObject(); + + auto properties = mGraphicsController->GetTextureProperties(*graphicsTexture); + + mRenderCallbackTextureBindings.emplace_back(graphicsTexture); + mRenderCallbackInput->textureBindings[i++] = properties.nativeHandle; + } + info.textureCount = mRenderCallbackTextureBindings.size(); + info.textureList = mRenderCallbackTextureBindings.data(); + } + + // pass render callback input + mRenderCallbackInput->size = size; + mRenderCallbackInput->projection = projectionMatrix; + + MatrixUtils::MultiplyProjectionMatrix(mRenderCallbackInput->mvp, modelViewMatrix, projectionMatrix); + + // submit draw + commandBuffer.DrawNative(&info); + return true; } // Prepare commands std::vector commands; - for( auto& cmd : mDrawCommands ) + for(auto& cmd : mDrawCommands) { if(cmd.queue == queueIndex) { - commands.emplace_back( &cmd ); + commands.emplace_back(&cmd); } } // Have commands but nothing to be drawn - abort if(!mDrawCommands.empty() && commands.empty()) { - return; + return false; } - // Get the program to use: - Program* program = mRenderDataProvider->GetShader().GetProgram(); - if( !program ) + // Set blending mode + if(!mDrawCommands.empty()) { - DALI_LOG_ERROR( "Failed to get program for shader at address %p.\n", reinterpret_cast< void* >( &mRenderDataProvider->GetShader() ) ); - return; + blend = (commands[0]->queue != DevelRenderer::RENDER_QUEUE_OPAQUE) && blend; } - //Set cull face mode - const Dali::Internal::SceneGraph::Camera* cam = instruction.GetCamera(); - if (cam->GetReflectionUsed()) + // Create Program + ShaderDataPtr shaderData = mRenderDataProvider->GetShader().GetShaderData(); + + Program* program = Program::New(*mProgramCache, + shaderData, + *mGraphicsController); + if(!program) { - auto adjFaceCullingMode = mFaceCullingMode; - switch( mFaceCullingMode ) + DALI_LOG_ERROR("Failed to get program for shader at address %p.\n", reinterpret_cast(&mRenderDataProvider->GetShader())); + return false; + } + + // If program doesn't have Gfx program object assigned yet, prepare it. + if(!program->GetGraphicsProgramPtr()) + { + const std::vector& vertShader = shaderData->GetShaderForPipelineStage(Graphics::PipelineStage::VERTEX_SHADER); + const std::vector& fragShader = shaderData->GetShaderForPipelineStage(Graphics::PipelineStage::FRAGMENT_SHADER); + Dali::Graphics::Shader& vertexShader = mShaderCache->GetShader( + vertShader, + Graphics::PipelineStage::VERTEX_SHADER, + shaderData->GetSourceMode()); + + Dali::Graphics::Shader& fragmentShader = mShaderCache->GetShader( + fragShader, + Graphics::PipelineStage::FRAGMENT_SHADER, + shaderData->GetSourceMode()); + + std::vector shaderStates{ + Graphics::ShaderState() + .SetShader(vertexShader) + .SetPipelineStage(Graphics::PipelineStage::VERTEX_SHADER), + Graphics::ShaderState() + .SetShader(fragmentShader) + .SetPipelineStage(Graphics::PipelineStage::FRAGMENT_SHADER)}; + + auto createInfo = Graphics::ProgramCreateInfo(); + createInfo.SetShaderState(shaderStates); + auto graphicsProgram = mGraphicsController->CreateProgram(createInfo, nullptr); + program->SetGraphicsProgram(std::move(graphicsProgram)); + } + + // Prepare the graphics pipeline. This may either re-use an existing pipeline or create a new one. + auto& pipeline = PrepareGraphicsPipeline(*program, instruction, node, blend); + + commandBuffer.BindPipeline(pipeline); + + BindTextures(commandBuffer, boundTextures); + + std::size_t nodeIndex = BuildUniformIndexMap(bufferIndex, node, size, *program); + + WriteUniformBuffer(bufferIndex, commandBuffer, program, instruction, node, modelMatrix, modelViewMatrix, viewMatrix, projectionMatrix, size, nodeIndex); + + bool drawn = false; // Draw can fail if there are no vertex buffers or they haven't been uploaded yet + // @todo We should detect this case much earlier to prevent unnecessary work + + // Reuse latest bound vertex attributes location, or Bind buffers to attribute locations. + if(ReuseLatestBoundVertexAttributes(mGeometry) || mGeometry->BindVertexAttributes(commandBuffer)) + { + if(mDrawCommands.empty()) { - case FaceCullingMode::Type::FRONT: - { - adjFaceCullingMode = FaceCullingMode::Type::BACK; - break; - } - case FaceCullingMode::Type::BACK: - { - adjFaceCullingMode = FaceCullingMode::Type::FRONT; - break; - } - default: + drawn = mGeometry->Draw(*mGraphicsController, commandBuffer, mIndexedDrawFirstElement, mIndexedDrawElementsCount); + } + else + { + for(auto& cmd : commands) { - // nothing to do, leave culling as it is + drawn |= mGeometry->Draw(*mGraphicsController, commandBuffer, cmd->firstIndex, cmd->elementCount); } } - context.CullFace( adjFaceCullingMode ); } else { - context.CullFace( mFaceCullingMode ); + // BindVertexAttributes failed. Reset cached geometry. + ReuseLatestBoundVertexAttributes(nullptr); + } + + return drawn; +} + +std::size_t Renderer::BuildUniformIndexMap(BufferIndex bufferIndex, const SceneGraph::NodeDataProvider& node, const Vector3& size, Program& program) +{ + // Check if the map has changed + DALI_ASSERT_DEBUG(mRenderDataProvider && "No Uniform map data provider available"); + + const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMapDataProvider(); + const SceneGraph::CollectedUniformMap& uniformMap = uniformMapDataProvider.GetCollectedUniformMap(); + const SceneGraph::UniformMap& uniformMapNode = node.GetNodeUniformMap(); + + bool updateMaps; + + // Usual case is to only have 1 node, however we do allow multiple nodes to reuse the same + // renderer, so we have to cache uniform map per render item (node / renderer pair). + + // Specially, if node don't have uniformMap, we mark nodePtr as nullptr. + // So, all nodes without uniformMap will share same UniformIndexMap, contains only render data providers. + const auto nodePtr = uniformMapNode.Count() ? &node : nullptr; + + const auto nodeChangeCounter = nodePtr ? uniformMapNode.GetChangeCounter() : 0; + const auto renderItemMapChangeCounter = uniformMap.GetChangeCounter(); + + auto iter = std::find_if(mNodeIndexMap.begin(), mNodeIndexMap.end(), [nodePtr](RenderItemLookup& element) { return element.node == nodePtr; }); + + std::size_t renderItemMapIndex; + if(iter == mNodeIndexMap.end()) + { + renderItemMapIndex = mUniformIndexMaps.size(); + RenderItemLookup renderItemLookup; + renderItemLookup.node = nodePtr; + renderItemLookup.index = renderItemMapIndex; + renderItemLookup.nodeChangeCounter = nodeChangeCounter; + renderItemLookup.renderItemMapChangeCounter = renderItemMapChangeCounter; + mNodeIndexMap.emplace_back(renderItemLookup); + + updateMaps = true; + mUniformIndexMaps.resize(mUniformIndexMaps.size() + 1); } + else + { + renderItemMapIndex = iter->index; - // Take the program into use so we can send uniforms to it - program->Use(); + updateMaps = (nodeChangeCounter != iter->nodeChangeCounter) || + (renderItemMapChangeCounter != iter->renderItemMapChangeCounter) || + (mUniformIndexMaps[renderItemMapIndex].size() == 0); + + iter->nodeChangeCounter = nodeChangeCounter; + iter->renderItemMapChangeCounter = renderItemMapChangeCounter; + } - if( DALI_LIKELY( BindTextures( context, *program, boundTextures ) ) ) + if(updateMaps || mShaderChanged) { - // Only set up and draw if we have textures and they are all valid + // Reset shader pointer + mShaderChanged = false; + + const uint32_t mapCount = uniformMap.Count(); + const uint32_t mapNodeCount = uniformMapNode.Count(); - // set projection and view matrix if program has not yet received them yet this frame - SetMatrices( *program, modelMatrix, viewMatrix, projectionMatrix, modelViewMatrix ); + mUniformIndexMaps[renderItemMapIndex].clear(); // Clear contents, but keep memory if we don't change size + mUniformIndexMaps[renderItemMapIndex].resize(mapCount + mapNodeCount); - // set color uniform - GLint loc = program->GetUniformLocation( Program::UNIFORM_COLOR ); - if( Program::UNIFORM_UNKNOWN != loc ) + // Copy uniform map into mUniformIndexMap + uint32_t mapIndex = 0; + for(; mapIndex < mapCount; ++mapIndex) { - const Vector4& color = node.GetRenderColor( bufferIndex ); - if( mPremultipledAlphaEnabled ) + mUniformIndexMaps[renderItemMapIndex][mapIndex].propertyValue = uniformMap.mUniformMap[mapIndex].propertyPtr; + mUniformIndexMaps[renderItemMapIndex][mapIndex].uniformName = uniformMap.mUniformMap[mapIndex].uniformName; + mUniformIndexMaps[renderItemMapIndex][mapIndex].uniformNameHash = uniformMap.mUniformMap[mapIndex].uniformNameHash; + mUniformIndexMaps[renderItemMapIndex][mapIndex].uniformNameHashNoArray = uniformMap.mUniformMap[mapIndex].uniformNameHashNoArray; + mUniformIndexMaps[renderItemMapIndex][mapIndex].arrayIndex = uniformMap.mUniformMap[mapIndex].arrayIndex; + } + + for(uint32_t nodeMapIndex = 0; nodeMapIndex < mapNodeCount; ++nodeMapIndex) + { + auto hash = uniformMapNode[nodeMapIndex].uniformNameHash; + auto& name = uniformMapNode[nodeMapIndex].uniformName; + bool found(false); + for(uint32_t i = 0; i < mapCount; ++i) { - float alpha = color.a * mRenderDataProvider->GetOpacity( bufferIndex ); - program->SetUniform4f( loc, color.r * alpha, color.g * alpha, color.b * alpha, alpha ); + if(mUniformIndexMaps[renderItemMapIndex][i].uniformNameHash == hash && + mUniformIndexMaps[renderItemMapIndex][i].uniformName == name) + { + mUniformIndexMaps[renderItemMapIndex][i].propertyValue = uniformMapNode[nodeMapIndex].propertyPtr; + found = true; + break; + } } - else + + if(!found) { - program->SetUniform4f( loc, color.r, color.g, color.b, color.a * mRenderDataProvider->GetOpacity( bufferIndex ) ); + mUniformIndexMaps[renderItemMapIndex][mapIndex].propertyValue = uniformMapNode[nodeMapIndex].propertyPtr; + mUniformIndexMaps[renderItemMapIndex][mapIndex].uniformName = uniformMapNode[nodeMapIndex].uniformName; + mUniformIndexMaps[renderItemMapIndex][mapIndex].uniformNameHash = uniformMapNode[nodeMapIndex].uniformNameHash; + mUniformIndexMaps[renderItemMapIndex][mapIndex].uniformNameHashNoArray = uniformMapNode[nodeMapIndex].uniformNameHashNoArray; + mUniformIndexMaps[renderItemMapIndex][mapIndex].arrayIndex = uniformMapNode[nodeMapIndex].arrayIndex; + ++mapIndex; } } - SetUniforms( bufferIndex, node, size, *program ); + mUniformIndexMaps[renderItemMapIndex].resize(mapIndex); + } + return renderItemMapIndex; +} + +void Renderer::WriteUniformBuffer( + BufferIndex bufferIndex, + Graphics::CommandBuffer& commandBuffer, + Program* program, + const SceneGraph::RenderInstruction& instruction, + const SceneGraph::NodeDataProvider& node, + const Matrix& modelMatrix, + const Matrix& modelViewMatrix, + const Matrix& viewMatrix, + const Matrix& projectionMatrix, + const Vector3& size, + std::size_t nodeIndex) +{ + // Create the UBO + uint32_t uboOffset{0u}; + + auto& reflection = mGraphicsController->GetProgramReflection(program->GetGraphicsProgram()); + + uint32_t uniformBlockAllocationBytes = program->GetUniformBlocksMemoryRequirements().totalSizeRequired; - if( mUpdateAttributesLocation || mGeometry->AttributesChanged() ) + // Create uniform buffer view from uniform buffer + Graphics::UniquePtr uboView{nullptr}; + if(uniformBlockAllocationBytes) + { + auto uboPoolView = mUniformBufferManager->GetUniformBufferViewPool(bufferIndex); + uboView = uboPoolView->CreateUniformBufferView(uniformBlockAllocationBytes); + } + + // update the uniform buffer + // pass shared UBO and offset, return new offset for next item to be used + // don't process bindings if there are no uniform buffers allocated + if(uboView) + { + auto uboCount = reflection.GetUniformBlockCount(); + mUniformBufferBindings.resize(uboCount); + + std::vector* bindings{&mUniformBufferBindings}; + + mUniformBufferBindings[0].buffer = uboView->GetBuffer(&mUniformBufferBindings[0].offset); + + // Write default uniforms + WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::MODEL_MATRIX), *uboView, modelMatrix); + WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::VIEW_MATRIX), *uboView, viewMatrix); + WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::PROJECTION_MATRIX), *uboView, projectionMatrix); + WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::MODEL_VIEW_MATRIX), *uboView, modelViewMatrix); + + auto mvpUniformInfo = program->GetDefaultUniform(Program::DefaultUniformIndex::MVP_MATRIX); + if(mvpUniformInfo && !mvpUniformInfo->name.empty()) { - mGeometry->GetAttributeLocationFromProgram( mAttributesLocation, *program, bufferIndex ); - mUpdateAttributesLocation = false; + Matrix modelViewProjectionMatrix(false); + MatrixUtils::MultiplyProjectionMatrix(modelViewProjectionMatrix, modelViewMatrix, projectionMatrix); + WriteDefaultUniform(mvpUniformInfo, *uboView, modelViewProjectionMatrix); } - if( mBlendingOptions.IsAdvancedBlendEquationApplied() && mPremultipledAlphaEnabled ) + auto normalUniformInfo = program->GetDefaultUniform(Program::DefaultUniformIndex::NORMAL_MATRIX); + if(normalUniformInfo && !normalUniformInfo->name.empty()) { - context.BlendBarrier(); + Matrix3 normalMatrix(modelViewMatrix); + normalMatrix.Invert(); + normalMatrix.Transpose(); + WriteDefaultUniform(normalUniformInfo, *uboView, normalMatrix); } - if(mDrawCommands.empty()) + Vector4 finalColor; ///< Applied renderer's opacity color + const Vector4& color = node.GetRenderColor(bufferIndex); ///< Actor's original color + if(mPremultipliedAlphaEnabled) { - SetBlending( context, blend ); - - mGeometry->Draw( context, - bufferIndex, - mAttributesLocation, - mIndexedDrawFirstElement, - mIndexedDrawElementsCount ); + const float& alpha = color.a * mRenderDataProvider->GetOpacity(bufferIndex); + finalColor = Vector4(color.r * alpha, color.g * alpha, color.b * alpha, alpha); } else { - for(auto& cmd : commands ) + finalColor = Vector4(color.r, color.g, color.b, color.a * mRenderDataProvider->GetOpacity(bufferIndex)); + } + WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::COLOR), *uboView, finalColor); + WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::ACTOR_COLOR), *uboView, color); + + // Write uniforms from the uniform map + FillUniformBuffer(*program, instruction, *uboView, bindings, uboOffset, bufferIndex, nodeIndex); + + // Write uSize in the end, as it shouldn't be overridable by dynamic properties. + WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::SIZE), *uboView, size); + + commandBuffer.BindUniformBuffers(*bindings); + } +} + +template +bool Renderer::WriteDefaultUniform(const Graphics::UniformInfo* uniformInfo, Render::UniformBufferView& ubo, const T& data) +{ + if(uniformInfo && !uniformInfo->name.empty()) + { + WriteUniform(ubo, *uniformInfo, data); + return true; + } + return false; +} + +template +void Renderer::WriteUniform(Render::UniformBufferView& ubo, const Graphics::UniformInfo& uniformInfo, const T& data) +{ + WriteUniform(ubo, uniformInfo, &data, sizeof(T)); +} + +void Renderer::WriteUniform(Render::UniformBufferView& ubo, const Graphics::UniformInfo& uniformInfo, const void* data, uint32_t size) +{ + ubo.Write(data, size, ubo.GetOffset() + uniformInfo.offset); +} + +void Renderer::FillUniformBuffer(Program& program, + const SceneGraph::RenderInstruction& instruction, + Render::UniformBufferView& ubo, + std::vector*& outBindings, + uint32_t& offset, + BufferIndex updateBufferIndex, + std::size_t nodeIndex) +{ + auto& reflection = mGraphicsController->GetProgramReflection(program.GetGraphicsProgram()); + auto uboCount = reflection.GetUniformBlockCount(); + + // Setup bindings + uint32_t dataOffset = offset; + for(auto i = 0u; i < uboCount; ++i) + { + mUniformBufferBindings[i].dataSize = reflection.GetUniformBlockSize(i); + mUniformBufferBindings[i].binding = reflection.GetUniformBlockBinding(i); + + dataOffset += GetUniformBufferDataAlignment(mUniformBufferBindings[i].dataSize); + mUniformBufferBindings[i].buffer = ubo.GetBuffer(&mUniformBufferBindings[i].offset); + + for(auto iter = mUniformIndexMaps[nodeIndex].begin(), + end = mUniformIndexMaps[nodeIndex].end(); + iter != end; + ++iter) + { + auto& uniform = *iter; + int arrayIndex = uniform.arrayIndex; + + if(!uniform.uniformFunc) { - if(cmd->queue == queueIndex ) + auto uniformInfo = Graphics::UniformInfo{}; + auto uniformFound = program.GetUniform(uniform.uniformName.GetStringView(), + uniform.uniformNameHash, + uniform.uniformNameHashNoArray, + uniformInfo); + + uniform.uniformOffset = uniformInfo.offset; + uniform.uniformLocation = uniformInfo.location; + + if(uniformFound) { - //Set blending mode - SetBlending(context, cmd->queue == DevelRenderer::RENDER_QUEUE_OPAQUE ? false : blend); - mGeometry->Draw(context, bufferIndex, mAttributesLocation, - cmd->firstIndex, cmd->elementCount); + auto dst = ubo.GetOffset() + uniformInfo.offset; + const auto typeSize = GetPropertyValueSizeForUniform((*iter).propertyValue->GetType()); + const auto dest = dst + static_cast(typeSize) * arrayIndex; + const auto func = GetPropertyValueGetter((*iter).propertyValue->GetType()); + + ubo.Write(&((*iter).propertyValue->*func)(updateBufferIndex), + typeSize, + dest); + + uniform.uniformSize = typeSize; + uniform.uniformFunc = func; } } + else + { + auto dst = ubo.GetOffset() + uniform.uniformOffset; + const auto typeSize = uniform.uniformSize; + const auto dest = dst + static_cast(typeSize) * arrayIndex; + const auto func = uniform.uniformFunc; + + ubo.Write(&((*iter).propertyValue->*func)(updateBufferIndex), + typeSize, + dest); + } } - mUpdated = false; } + // write output bindings + outBindings = &mUniformBufferBindings; + + // Update offset + offset = dataOffset; } -void Renderer::SetSortAttributes( BufferIndex bufferIndex, - SceneGraph::RenderInstructionProcessor::SortAttributes& sortAttributes ) const +void Renderer::SetSortAttributes(SceneGraph::RenderInstructionProcessor::SortAttributes& sortAttributes) const { - sortAttributes.shader = &( mRenderDataProvider->GetShader() ); + sortAttributes.shader = &(mRenderDataProvider->GetShader()); sortAttributes.geometry = mGeometry; } -void Renderer::SetShaderChanged( bool value ) +void Renderer::SetShaderChanged(bool value) { mShaderChanged = value; } -bool Renderer::Updated(BufferIndex bufferIndex, const SceneGraph::NodeDataProvider* node) +bool Renderer::Updated(BufferIndex bufferIndex) { - if (mUpdated) - { - mUpdated = false; - return true; - } - - if (mShaderChanged || mUpdateAttributesLocation || mGeometry->AttributesChanged()) + if(mRenderCallback || mShaderChanged || mGeometry->AttributesChanged() || mRenderDataProvider->IsUpdated()) { return true; } - for( const auto& texture : mRenderDataProvider->GetTextures() ) + auto* textures = mRenderDataProvider->GetTextures(); + if(textures) { - if (texture && texture->IsNativeImage()) + for(auto iter = textures->Begin(), end = textures->End(); iter < end; ++iter) { - return true; + auto texture = *iter; + if(texture && texture->Updated()) + { + return true; + } } } + return false; +} - uint64_t hash = 0xc70f6907UL; - const SceneGraph::CollectedUniformMap& uniformMapNode = node->GetUniformMap( bufferIndex ); - for(const auto& uniformProperty : uniformMapNode) - { - hash = uniformProperty.propertyPtr->Hash(bufferIndex, hash); - } +Vector4 Renderer::GetVisualTransformedUpdateArea(BufferIndex bufferIndex, const Vector4& originalUpdateArea) const noexcept +{ + return mRenderDataProvider->GetVisualTransformedUpdateArea(bufferIndex, originalUpdateArea); +} - const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap(); - const SceneGraph::CollectedUniformMap& uniformMap = uniformMapDataProvider.GetUniformMap( bufferIndex ); - for(const auto& uniformProperty : uniformMap) - { - hash = uniformProperty.propertyPtr->Hash(bufferIndex, hash); - } +Graphics::Pipeline& Renderer::PrepareGraphicsPipeline( + Program& program, + const Dali::Internal::SceneGraph::RenderInstruction& instruction, + const SceneGraph::NodeDataProvider& node, + bool blend) +{ + // Prepare query info + PipelineCacheQueryInfo queryInfo{}; + queryInfo.program = &program; + queryInfo.renderer = this; + queryInfo.geometry = mGeometry; + queryInfo.blendingEnabled = blend; + queryInfo.blendingOptions = &mBlendingOptions; + queryInfo.alphaPremultiplied = mPremultipliedAlphaEnabled; + queryInfo.cameraUsingReflection = instruction.GetCamera()->GetReflectionUsed(); - if (mUniformsHash != hash) - { - mUniformsHash = hash; - return true; - } + queryInfo.GenerateHash(); - return false; + // Find or generate new pipeline. + auto pipelineResult = mPipelineCache->GetPipeline(queryInfo, true); + + // should be never null? + return *pipelineResult.pipeline; } -} // namespace SceneGraph +void Renderer::SetRenderCallback(RenderCallback* callback) +{ + mRenderCallback = callback; +} -} // namespace Internal +} // namespace Render -} // namespace Dali +} // namespace Dali::Internal