/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include <memory.h>
// INTERNAL INCLUDES
-#include <dali/public-api/actors/sampling.h>
-#include <dali/public-api/common/dali-common.h>
-#include <dali/public-api/common/stage.h>
-#include <dali/public-api/render-tasks/render-task.h>
#include <dali/devel-api/threading/thread-pool.h>
-#include <dali/integration-api/debug.h>
#include <dali/integration-api/core.h>
-#include <dali/integration-api/gl-context-helper-abstraction.h>
-#include <dali/internal/common/owner-pointer.h>
+
#include <dali/internal/event/common/scene-impl.h>
+
+#include <dali/internal/update/common/scene-graph-scene.h>
+#include <dali/internal/update/render-tasks/scene-graph-camera.h>
+
#include <dali/internal/render/common/render-algorithms.h>
#include <dali/internal/render/common/render-debug.h>
-#include <dali/internal/render/common/render-tracker.h>
-#include <dali/internal/render/common/render-instruction-container.h>
#include <dali/internal/render/common/render-instruction.h>
-#include <dali/internal/render/gl-resources/context.h>
+#include <dali/internal/render/common/render-tracker.h>
#include <dali/internal/render/queue/render-queue.h>
+#include <dali/internal/render/renderers/pipeline-cache.h>
#include <dali/internal/render/renderers/render-frame-buffer.h>
-#include <dali/internal/render/renderers/render-geometry.h>
-#include <dali/internal/render/renderers/render-renderer.h>
-#include <dali/internal/render/renderers/render-sampler.h>
+#include <dali/internal/render/renderers/render-texture.h>
+#include <dali/internal/render/renderers/shader-cache.h>
+#include <dali/internal/render/renderers/uniform-buffer-manager.h>
+#include <dali/internal/render/renderers/uniform-buffer-view-pool.h>
#include <dali/internal/render/shaders/program-controller.h>
-#include <dali/internal/update/common/scene-graph-scene.h>
+
+#include <memory>
namespace Dali
{
-
namespace Internal
{
-
namespace SceneGraph
{
-
#if defined(DEBUG_ENABLED)
namespace
{
-Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RENDER_MANAGER" );
+Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RENDER_MANAGER");
} // unnamed namespace
#endif
+namespace
+{
+inline Graphics::Rect2D RecalculateScissorArea(Graphics::Rect2D scissorArea, int orientation, Rect<int32_t> viewportRect)
+{
+ Graphics::Rect2D newScissorArea;
+
+ if(orientation == 90)
+ {
+ newScissorArea.x = viewportRect.height - (scissorArea.y + scissorArea.height);
+ newScissorArea.y = scissorArea.x;
+ newScissorArea.width = scissorArea.height;
+ newScissorArea.height = scissorArea.width;
+ }
+ else if(orientation == 180)
+ {
+ newScissorArea.x = viewportRect.width - (scissorArea.x + scissorArea.width);
+ newScissorArea.y = viewportRect.height - (scissorArea.y + scissorArea.height);
+ newScissorArea.width = scissorArea.width;
+ newScissorArea.height = scissorArea.height;
+ }
+ else if(orientation == 270)
+ {
+ newScissorArea.x = scissorArea.y;
+ newScissorArea.y = viewportRect.width - (scissorArea.x + scissorArea.width);
+ newScissorArea.width = scissorArea.height;
+ newScissorArea.height = scissorArea.width;
+ }
+ else
+ {
+ newScissorArea.x = scissorArea.x;
+ newScissorArea.y = scissorArea.y;
+ newScissorArea.width = scissorArea.width;
+ newScissorArea.height = scissorArea.height;
+ }
+ return newScissorArea;
+}
+} // namespace
/**
* Structure to contain internal data
*/
struct RenderManager::Impl
{
- Impl( Integration::GlAbstraction& glAbstraction,
- Integration::GlSyncAbstraction& glSyncAbstraction,
- Integration::GlContextHelperAbstraction& glContextHelperAbstraction,
- Integration::DepthBufferAvailable depthBufferAvailableParam,
- Integration::StencilBufferAvailable stencilBufferAvailableParam )
- : context( glAbstraction, &sceneContextContainer ),
- currentContext( &context ),
- glAbstraction( glAbstraction ),
- glSyncAbstraction( glSyncAbstraction ),
- glContextHelperAbstraction( glContextHelperAbstraction ),
+ Impl(Graphics::Controller& graphicsController,
+ Integration::DepthBufferAvailable depthBufferAvailableParam,
+ Integration::StencilBufferAvailable stencilBufferAvailableParam,
+ Integration::PartialUpdateAvailable partialUpdateAvailableParam)
+ : graphicsController(graphicsController),
renderQueue(),
- renderAlgorithms(),
- frameCount( 0u ),
- renderBufferIndex( SceneGraphBuffers::INITIAL_UPDATE_BUFFER_INDEX ),
- defaultSurfaceRect(),
+ renderAlgorithms(graphicsController),
+ frameCount(0u),
+ renderBufferIndex(SceneGraphBuffers::INITIAL_UPDATE_BUFFER_INDEX),
rendererContainer(),
samplerContainer(),
textureContainer(),
frameBufferContainer(),
- lastFrameWasRendered( false ),
- programController( glAbstraction ),
- depthBufferAvailable( depthBufferAvailableParam ),
- stencilBufferAvailable( stencilBufferAvailableParam )
+ lastFrameWasRendered(false),
+ programController(graphicsController),
+ shaderCache(graphicsController),
+ depthBufferAvailable(depthBufferAvailableParam),
+ stencilBufferAvailable(stencilBufferAvailableParam),
+ partialUpdateAvailable(partialUpdateAvailableParam)
{
- // Create thread pool with just one thread ( there may be a need to create more threads in the future ).
- threadPool = std::unique_ptr<Dali::ThreadPool>( new Dali::ThreadPool() );
- threadPool->Initialize( 1u );
- }
+ // Create thread pool with just one thread ( there may be a need to create more threads in the future ).
+ threadPool = std::make_unique<Dali::ThreadPool>();
+ threadPool->Initialize(1u);
- ~Impl()
- {
- threadPool.reset( nullptr ); // reset now to maintain correct destruction order
+ uniformBufferManager = std::make_unique<Render::UniformBufferManager>(&graphicsController);
+ pipelineCache = std::make_unique<Render::PipelineCache>(graphicsController);
}
- void AddRenderTracker( Render::RenderTracker* renderTracker )
- {
- DALI_ASSERT_DEBUG( renderTracker != NULL );
- mRenderTrackers.PushBack( renderTracker );
- }
-
- void RemoveRenderTracker( Render::RenderTracker* renderTracker )
- {
- mRenderTrackers.EraseObject( renderTracker );
- }
-
- Context* CreateSceneContext()
+ ~Impl()
{
- sceneContextContainer.push_back( new Context( glAbstraction ) );
- return sceneContextContainer[ sceneContextContainer.size() - 1 ];
+ threadPool.reset(nullptr); // reset now to maintain correct destruction order
}
- void DestroySceneContext( Context* sceneContext )
+ void AddRenderTracker(Render::RenderTracker* renderTracker)
{
- auto iter = std::find( sceneContextContainer.begin(), sceneContextContainer.end(), sceneContext );
- if( iter != sceneContextContainer.end() )
- {
- sceneContextContainer.erase( iter );
- }
+ DALI_ASSERT_DEBUG(renderTracker != nullptr);
+ mRenderTrackers.PushBack(renderTracker);
}
- Context* ReplaceSceneContext( Context* oldSceneContext )
+ void RemoveRenderTracker(Render::RenderTracker* renderTracker)
{
- Context* newContext = new Context( glAbstraction );
- std::replace( sceneContextContainer.begin(), sceneContextContainer.end(), oldSceneContext, newContext );
- return newContext;
+ mRenderTrackers.EraseObject(renderTracker);
}
void UpdateTrackers()
{
- for( auto&& iter : mRenderTrackers )
+ for(auto&& iter : mRenderTrackers)
{
iter->PollSyncObject();
}
}
// the order is important for destruction,
- // programs are owned by context at the moment.
- Context context; ///< Holds the GL state of the share resource context
- Context* currentContext; ///< Holds the GL state of the current context for rendering
- std::vector< Context* > sceneContextContainer; ///< List of owned contexts holding the GL state per scene
- Integration::GlAbstraction& glAbstraction; ///< GL abstraction
- Integration::GlSyncAbstraction& glSyncAbstraction; ///< GL sync abstraction
- Integration::GlContextHelperAbstraction& glContextHelperAbstraction; ///< GL context helper abstraction
- RenderQueue renderQueue; ///< A message queue for receiving messages from the update-thread.
+ Graphics::Controller& graphicsController;
+ RenderQueue renderQueue; ///< A message queue for receiving messages from the update-thread.
- std::vector< SceneGraph::Scene* > sceneContainer; ///< List of pointers to the scene graph objects of the scenes
+ std::vector<SceneGraph::Scene*> sceneContainer; ///< List of pointers to the scene graph objects of the scenes
- Render::RenderAlgorithms renderAlgorithms; ///< The RenderAlgorithms object is used to action the renders required by a RenderInstruction
+ Render::RenderAlgorithms renderAlgorithms; ///< The RenderAlgorithms object is used to action the renders required by a RenderInstruction
- uint32_t frameCount; ///< The current frame count
- BufferIndex renderBufferIndex; ///< The index of the buffer to read from; this is opposite of the "update" buffer
+ uint32_t frameCount; ///< The current frame count
+ BufferIndex renderBufferIndex; ///< The index of the buffer to read from; this is opposite of the "update" buffer
- Rect<int32_t> defaultSurfaceRect; ///< Rectangle for the default surface we are rendering to
+ OwnerContainer<Render::Renderer*> rendererContainer; ///< List of owned renderers
+ OwnerContainer<Render::Sampler*> samplerContainer; ///< List of owned samplers
+ OwnerContainer<Render::Texture*> textureContainer; ///< List of owned textures
+ OwnerContainer<Render::FrameBuffer*> frameBufferContainer; ///< List of owned framebuffers
+ OwnerContainer<Render::VertexBuffer*> vertexBufferContainer; ///< List of owned vertex buffers
+ OwnerContainer<Render::Geometry*> geometryContainer; ///< List of owned Geometries
- OwnerContainer< Render::Renderer* > rendererContainer; ///< List of owned renderers
- OwnerContainer< Render::Sampler* > samplerContainer; ///< List of owned samplers
- OwnerContainer< Render::Texture* > textureContainer; ///< List of owned textures
- OwnerContainer< Render::FrameBuffer* > frameBufferContainer; ///< List of owned framebuffers
- OwnerContainer< Render::PropertyBuffer* > propertyBufferContainer; ///< List of owned property buffers
- OwnerContainer< Render::Geometry* > geometryContainer; ///< List of owned Geometries
+ bool lastFrameWasRendered; ///< Keeps track of the last frame being rendered due to having render instructions
- bool lastFrameWasRendered; ///< Keeps track of the last frame being rendered due to having render instructions
+ OwnerContainer<Render::RenderTracker*> mRenderTrackers; ///< List of render trackers
- OwnerContainer< Render::RenderTracker* > mRenderTrackers; ///< List of render trackers
+ ProgramController programController; ///< Owner of the programs
+ Render::ShaderCache shaderCache; ///< The cache for the graphics shaders
- ProgramController programController; ///< Owner of the GL programs
+ std::unique_ptr<Render::UniformBufferManager> uniformBufferManager; ///< The uniform buffer manager
+ std::unique_ptr<Render::PipelineCache> pipelineCache;
- Integration::DepthBufferAvailable depthBufferAvailable; ///< Whether the depth buffer is available
- Integration::StencilBufferAvailable stencilBufferAvailable; ///< Whether the stencil buffer is available
+ Integration::DepthBufferAvailable depthBufferAvailable; ///< Whether the depth buffer is available
+ Integration::StencilBufferAvailable stencilBufferAvailable; ///< Whether the stencil buffer is available
+ Integration::PartialUpdateAvailable partialUpdateAvailable; ///< Whether the partial update is available
- std::unique_ptr<Dali::ThreadPool> threadPool; ///< The thread pool
- Vector<GLuint> boundTextures; ///< The textures bound for rendering
- Vector<GLuint> textureDependencyList; ///< The dependency list of binded textures
+ std::unique_ptr<Dali::ThreadPool> threadPool; ///< The thread pool
+ Vector<Graphics::Texture*> boundTextures; ///< The textures bound for rendering
+ Vector<Graphics::Texture*> textureDependencyList; ///< The dependency list of bound textures
};
-RenderManager* RenderManager::New( Integration::GlAbstraction& glAbstraction,
- Integration::GlSyncAbstraction& glSyncAbstraction,
- Integration::GlContextHelperAbstraction& glContextHelperAbstraction,
- Integration::DepthBufferAvailable depthBufferAvailable,
- Integration::StencilBufferAvailable stencilBufferAvailable )
-{
- RenderManager* manager = new RenderManager;
- manager->mImpl = new Impl( glAbstraction,
- glSyncAbstraction,
- glContextHelperAbstraction,
- depthBufferAvailable,
- stencilBufferAvailable );
+RenderManager* RenderManager::New(Graphics::Controller& graphicsController,
+ Integration::DepthBufferAvailable depthBufferAvailable,
+ Integration::StencilBufferAvailable stencilBufferAvailable,
+ Integration::PartialUpdateAvailable partialUpdateAvailable)
+{
+ auto* manager = new RenderManager;
+ manager->mImpl = new Impl(graphicsController,
+ depthBufferAvailable,
+ stencilBufferAvailable,
+ partialUpdateAvailable);
return manager;
}
RenderManager::RenderManager()
-: mImpl(NULL)
+: mImpl(nullptr)
{
}
return mImpl->renderQueue;
}
-void RenderManager::ContextCreated()
-{
- mImpl->context.GlContextCreated();
- mImpl->programController.GlContextCreated();
-
- // renderers, textures and gpu buffers cannot reinitialize themselves
- // so they rely on someone reloading the data for them
-}
-
-void RenderManager::ContextDestroyed()
-{
- mImpl->context.GlContextDestroyed();
- mImpl->programController.GlContextDestroyed();
-
- //Inform textures
- for( auto&& texture : mImpl->textureContainer )
- {
- texture->GlContextDestroyed();
- }
-
- //Inform framebuffers
- for( auto&& framebuffer : mImpl->frameBufferContainer )
- {
- framebuffer->GlContextDestroyed();
- }
-
- // inform renderers
- for( auto&& renderer : mImpl->rendererContainer )
- {
- renderer->GlContextDestroyed();
- }
-
- // inform scenes
- for( auto&& scene : mImpl->sceneContainer )
- {
- scene->GlContextDestroyed();
- }
-}
-
-void RenderManager::SetShaderSaver( ShaderSaver& upstream )
-{
- mImpl->programController.SetShaderSaver( upstream );
-}
-
-void RenderManager::SetDefaultSurfaceRect(const Rect<int32_t>& rect)
+void RenderManager::SetShaderSaver(ShaderSaver& upstream)
{
- mImpl->defaultSurfaceRect = rect;
}
-void RenderManager::AddRenderer( OwnerPointer< Render::Renderer >& renderer )
+void RenderManager::AddRenderer(OwnerPointer<Render::Renderer>& renderer)
{
// Initialize the renderer as we are now in render thread
- renderer->Initialize( mImpl->context );
+ renderer->Initialize(mImpl->graphicsController, mImpl->programController, mImpl->shaderCache, *(mImpl->uniformBufferManager.get()), *(mImpl->pipelineCache.get()));
- mImpl->rendererContainer.PushBack( renderer.Release() );
+ mImpl->rendererContainer.PushBack(renderer.Release());
}
-void RenderManager::RemoveRenderer( Render::Renderer* renderer )
+void RenderManager::RemoveRenderer(Render::Renderer* renderer)
{
- mImpl->rendererContainer.EraseObject( renderer );
+ mImpl->rendererContainer.EraseObject(renderer);
}
-void RenderManager::AddSampler( OwnerPointer< Render::Sampler >& sampler )
+void RenderManager::AddSampler(OwnerPointer<Render::Sampler>& sampler)
{
- mImpl->samplerContainer.PushBack( sampler.Release() );
+ sampler->Initialize(mImpl->graphicsController);
+ mImpl->samplerContainer.PushBack(sampler.Release());
}
-void RenderManager::RemoveSampler( Render::Sampler* sampler )
+void RenderManager::RemoveSampler(Render::Sampler* sampler)
{
- mImpl->samplerContainer.EraseObject( sampler );
+ mImpl->samplerContainer.EraseObject(sampler);
}
-void RenderManager::AddTexture( OwnerPointer< Render::Texture >& texture )
+void RenderManager::AddTexture(OwnerPointer<Render::Texture>& texture)
{
- texture->Initialize( mImpl->context );
- mImpl->textureContainer.PushBack( texture.Release() );
+ texture->Initialize(mImpl->graphicsController);
+ mImpl->textureContainer.PushBack(texture.Release());
}
-void RenderManager::RemoveTexture( Render::Texture* texture )
+void RenderManager::RemoveTexture(Render::Texture* texture)
{
- DALI_ASSERT_DEBUG( NULL != texture );
+ DALI_ASSERT_DEBUG(NULL != texture);
// Find the texture, use reference to pointer so we can do the erase safely
- for ( auto&& iter : mImpl->textureContainer )
+ for(auto&& iter : mImpl->textureContainer)
{
- if ( iter == texture )
+ if(iter == texture)
{
- texture->Destroy( mImpl->context );
- mImpl->textureContainer.Erase( &iter ); // Texture found; now destroy it
+ texture->Destroy();
+ mImpl->textureContainer.Erase(&iter); // Texture found; now destroy it
return;
}
}
}
-void RenderManager::UploadTexture( Render::Texture* texture, PixelDataPtr pixelData, const Texture::UploadParams& params )
+void RenderManager::UploadTexture(Render::Texture* texture, PixelDataPtr pixelData, const Texture::UploadParams& params)
{
- texture->Upload( mImpl->context, pixelData, params );
+ texture->Upload(pixelData, params);
}
-void RenderManager::GenerateMipmaps( Render::Texture* texture )
+void RenderManager::GenerateMipmaps(Render::Texture* texture)
{
- texture->GenerateMipmaps( mImpl->context );
+ texture->GenerateMipmaps();
}
-void RenderManager::SetFilterMode( Render::Sampler* sampler, uint32_t minFilterMode, uint32_t magFilterMode )
+void RenderManager::SetFilterMode(Render::Sampler* sampler, uint32_t minFilterMode, uint32_t magFilterMode)
{
- sampler->mMinificationFilter = static_cast<Dali::FilterMode::Type>(minFilterMode);
- sampler->mMagnificationFilter = static_cast<Dali::FilterMode::Type>(magFilterMode );
+ sampler->SetFilterMode(static_cast<Dali::FilterMode::Type>(minFilterMode),
+ static_cast<Dali::FilterMode::Type>(magFilterMode));
}
-void RenderManager::SetWrapMode( Render::Sampler* sampler, uint32_t rWrapMode, uint32_t sWrapMode, uint32_t tWrapMode )
+void RenderManager::SetWrapMode(Render::Sampler* sampler, uint32_t rWrapMode, uint32_t sWrapMode, uint32_t tWrapMode)
{
- sampler->mRWrapMode = static_cast<Dali::WrapMode::Type>(rWrapMode);
- sampler->mSWrapMode = static_cast<Dali::WrapMode::Type>(sWrapMode);
- sampler->mTWrapMode = static_cast<Dali::WrapMode::Type>(tWrapMode);
+ sampler->SetWrapMode(static_cast<Dali::WrapMode::Type>(rWrapMode),
+ static_cast<Dali::WrapMode::Type>(sWrapMode),
+ static_cast<Dali::WrapMode::Type>(tWrapMode));
}
-void RenderManager::AddFrameBuffer( OwnerPointer< Render::FrameBuffer >& frameBuffer )
+void RenderManager::AddFrameBuffer(OwnerPointer<Render::FrameBuffer>& frameBuffer)
{
Render::FrameBuffer* frameBufferPtr = frameBuffer.Release();
- mImpl->frameBufferContainer.PushBack( frameBufferPtr );
- frameBufferPtr->Initialize( mImpl->context );
+ mImpl->frameBufferContainer.PushBack(frameBufferPtr);
+ frameBufferPtr->Initialize(mImpl->graphicsController);
}
-void RenderManager::RemoveFrameBuffer( Render::FrameBuffer* frameBuffer )
+void RenderManager::RemoveFrameBuffer(Render::FrameBuffer* frameBuffer)
{
- DALI_ASSERT_DEBUG( NULL != frameBuffer );
+ DALI_ASSERT_DEBUG(nullptr != frameBuffer);
// Find the sampler, use reference so we can safely do the erase
- for ( auto&& iter : mImpl->frameBufferContainer )
+ for(auto&& iter : mImpl->frameBufferContainer)
{
- if ( iter == frameBuffer )
+ if(iter == frameBuffer)
{
- frameBuffer->Destroy( mImpl->context );
- mImpl->frameBufferContainer.Erase( &iter ); // frameBuffer found; now destroy it
+ frameBuffer->Destroy();
+ mImpl->frameBufferContainer.Erase(&iter); // frameBuffer found; now destroy it
break;
}
}
}
-void RenderManager::InitializeScene( SceneGraph::Scene* scene )
+
+void RenderManager::InitializeScene(SceneGraph::Scene* scene)
{
- scene->Initialize( *mImpl->CreateSceneContext() );
- mImpl->sceneContainer.push_back( scene );
+ scene->Initialize(mImpl->graphicsController, mImpl->depthBufferAvailable, mImpl->stencilBufferAvailable);
+ mImpl->sceneContainer.push_back(scene);
}
-void RenderManager::UninitializeScene( SceneGraph::Scene* scene )
+void RenderManager::UninitializeScene(SceneGraph::Scene* scene)
{
- mImpl->DestroySceneContext( scene->GetContext() );
-
- auto iter = std::find( mImpl->sceneContainer.begin(), mImpl->sceneContainer.end(), scene );
- if( iter != mImpl->sceneContainer.end() )
+ auto iter = std::find(mImpl->sceneContainer.begin(), mImpl->sceneContainer.end(), scene);
+ if(iter != mImpl->sceneContainer.end())
{
- mImpl->sceneContainer.erase( iter );
+ mImpl->sceneContainer.erase(iter);
}
}
-void RenderManager::SurfaceReplaced( SceneGraph::Scene* scene )
+void RenderManager::SurfaceReplaced(SceneGraph::Scene* scene)
{
- Context* newContext = mImpl->ReplaceSceneContext( scene->GetContext() );
- scene->Initialize( *newContext );
+ scene->Initialize(mImpl->graphicsController, mImpl->depthBufferAvailable, mImpl->stencilBufferAvailable);
}
-void RenderManager::AttachColorTextureToFrameBuffer( Render::FrameBuffer* frameBuffer, Render::Texture* texture, uint32_t mipmapLevel, uint32_t layer )
+void RenderManager::AttachColorTextureToFrameBuffer(Render::FrameBuffer* frameBuffer, Render::Texture* texture, uint32_t mipmapLevel, uint32_t layer)
{
- frameBuffer->AttachColorTexture( mImpl->context, texture, mipmapLevel, layer );
+ frameBuffer->AttachColorTexture(texture, mipmapLevel, layer);
}
-void RenderManager::AttachDepthTextureToFrameBuffer( Render::FrameBuffer* frameBuffer, Render::Texture* texture, uint32_t mipmapLevel )
+void RenderManager::AttachDepthTextureToFrameBuffer(Render::FrameBuffer* frameBuffer, Render::Texture* texture, uint32_t mipmapLevel)
{
- frameBuffer->AttachDepthTexture( mImpl->context, texture, mipmapLevel );
+ frameBuffer->AttachDepthTexture(texture, mipmapLevel);
}
-void RenderManager::AttachDepthStencilTextureToFrameBuffer( Render::FrameBuffer* frameBuffer, Render::Texture* texture, uint32_t mipmapLevel )
+void RenderManager::AttachDepthStencilTextureToFrameBuffer(Render::FrameBuffer* frameBuffer, Render::Texture* texture, uint32_t mipmapLevel)
{
- frameBuffer->AttachDepthStencilTexture( mImpl->context, texture, mipmapLevel );
+ frameBuffer->AttachDepthStencilTexture(texture, mipmapLevel);
}
-void RenderManager::AddPropertyBuffer( OwnerPointer< Render::PropertyBuffer >& propertyBuffer )
+void RenderManager::AddVertexBuffer(OwnerPointer<Render::VertexBuffer>& vertexBuffer)
{
- mImpl->propertyBufferContainer.PushBack( propertyBuffer.Release() );
+ mImpl->vertexBufferContainer.PushBack(vertexBuffer.Release());
}
-void RenderManager::RemovePropertyBuffer( Render::PropertyBuffer* propertyBuffer )
+void RenderManager::RemoveVertexBuffer(Render::VertexBuffer* vertexBuffer)
{
- mImpl->propertyBufferContainer.EraseObject( propertyBuffer );
+ mImpl->vertexBufferContainer.EraseObject(vertexBuffer);
}
-void RenderManager::SetPropertyBufferFormat( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Render::PropertyBuffer::Format>& format )
+void RenderManager::SetVertexBufferFormat(Render::VertexBuffer* vertexBuffer, OwnerPointer<Render::VertexBuffer::Format>& format)
{
- propertyBuffer->SetFormat( format.Release() );
+ vertexBuffer->SetFormat(format.Release());
}
-void RenderManager::SetPropertyBufferData( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Vector<uint8_t> >& data, uint32_t size )
+void RenderManager::SetVertexBufferData(Render::VertexBuffer* vertexBuffer, OwnerPointer<Vector<uint8_t>>& data, uint32_t size)
{
- propertyBuffer->SetData( data.Release(), size );
+ vertexBuffer->SetData(data.Release(), size);
}
-void RenderManager::SetIndexBuffer( Render::Geometry* geometry, Dali::Vector<uint16_t>& indices )
+void RenderManager::SetIndexBuffer(Render::Geometry* geometry, Dali::Vector<uint16_t>& indices)
{
- geometry->SetIndexBuffer( indices );
+ geometry->SetIndexBuffer(indices);
}
-void RenderManager::AddGeometry( OwnerPointer< Render::Geometry >& geometry )
+void RenderManager::AddGeometry(OwnerPointer<Render::Geometry>& geometry)
{
- mImpl->geometryContainer.PushBack( geometry.Release() );
+ mImpl->geometryContainer.PushBack(geometry.Release());
}
-void RenderManager::RemoveGeometry( Render::Geometry* geometry )
+void RenderManager::RemoveGeometry(Render::Geometry* geometry)
{
- mImpl->geometryContainer.EraseObject( geometry );
+ auto it = std::find_if(mImpl->geometryContainer.begin(), mImpl->geometryContainer.end(), [geometry](auto& item) {
+ return geometry == item;
+ });
+
+ if(it != mImpl->geometryContainer.end())
+ {
+ mImpl->geometryContainer.Erase(it);
+ }
}
-void RenderManager::AttachVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
+void RenderManager::AttachVertexBuffer(Render::Geometry* geometry, Render::VertexBuffer* vertexBuffer)
{
- DALI_ASSERT_DEBUG( NULL != geometry );
+ DALI_ASSERT_DEBUG(nullptr != geometry);
// Find the geometry
- for ( auto&& iter : mImpl->geometryContainer )
+ for(auto&& iter : mImpl->geometryContainer)
{
- if ( iter == geometry )
+ if(iter == geometry)
{
- iter->AddPropertyBuffer( propertyBuffer );
+ iter->AddVertexBuffer(vertexBuffer);
break;
}
}
}
-void RenderManager::RemoveVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
+void RenderManager::RemoveVertexBuffer(Render::Geometry* geometry, Render::VertexBuffer* vertexBuffer)
{
- DALI_ASSERT_DEBUG( NULL != geometry );
+ DALI_ASSERT_DEBUG(nullptr != geometry);
// Find the geometry
- for ( auto&& iter : mImpl->geometryContainer )
+ for(auto&& iter : mImpl->geometryContainer)
{
- if ( iter == geometry )
+ if(iter == geometry)
{
- iter->RemovePropertyBuffer( propertyBuffer );
+ iter->RemoveVertexBuffer(vertexBuffer);
break;
}
}
}
-void RenderManager::SetGeometryType( Render::Geometry* geometry, uint32_t geometryType )
+void RenderManager::SetGeometryType(Render::Geometry* geometry, uint32_t geometryType)
{
- geometry->SetType( Render::Geometry::Type(geometryType) );
+ geometry->SetType(Render::Geometry::Type(geometryType));
}
-void RenderManager::AddRenderTracker( Render::RenderTracker* renderTracker )
+void RenderManager::AddRenderTracker(Render::RenderTracker* renderTracker)
{
mImpl->AddRenderTracker(renderTracker);
}
-void RenderManager::RemoveRenderTracker( Render::RenderTracker* renderTracker )
+void RenderManager::RemoveRenderTracker(Render::RenderTracker* renderTracker)
{
mImpl->RemoveRenderTracker(renderTracker);
}
-ProgramCache* RenderManager::GetProgramCache()
+void RenderManager::PreRender(Integration::RenderStatus& status, bool forceClear, bool uploadOnly)
{
- return &(mImpl->programController);
-}
+ DALI_PRINT_RENDER_START(mImpl->renderBufferIndex);
-void RenderManager::PreRender( Integration::RenderStatus& status, bool forceClear, bool uploadOnly )
-{
- DALI_PRINT_RENDER_START( mImpl->renderBufferIndex );
-
- // Core::Render documents that GL context must be current before calling Render
- DALI_ASSERT_DEBUG( mImpl->context.IsGlContextCreated() );
+ // Rollback
+ mImpl->uniformBufferManager->GetUniformBufferViewPool(mImpl->renderBufferIndex)->Rollback();
// Increment the frame count at the beginning of each frame
++mImpl->frameCount;
// Process messages queued during previous update
- mImpl->renderQueue.ProcessMessages( mImpl->renderBufferIndex );
+ mImpl->renderQueue.ProcessMessages(mImpl->renderBufferIndex);
uint32_t count = 0u;
- for( uint32_t i = 0; i < mImpl->sceneContainer.size(); ++i )
+ for(auto& i : mImpl->sceneContainer)
{
- count += mImpl->sceneContainer[i]->GetRenderInstructions().Count( mImpl->renderBufferIndex );
+ count += i->GetRenderInstructions().Count(mImpl->renderBufferIndex);
}
const bool haveInstructions = count > 0u;
- DALI_LOG_INFO( gLogFilter, Debug::General,
- "Render: haveInstructions(%s) || mImpl->lastFrameWasRendered(%s) || forceClear(%s)\n",
- haveInstructions ? "true" : "false",
- mImpl->lastFrameWasRendered ? "true" : "false",
- forceClear ? "true" : "false" );
+ DALI_LOG_INFO(gLogFilter, Debug::General, "Render: haveInstructions(%s) || mImpl->lastFrameWasRendered(%s) || forceClear(%s)\n", haveInstructions ? "true" : "false", mImpl->lastFrameWasRendered ? "true" : "false", forceClear ? "true" : "false");
// Only render if we have instructions to render, or the last frame was rendered (and therefore a clear is required).
- if( haveInstructions || mImpl->lastFrameWasRendered || forceClear )
+ if(haveInstructions || mImpl->lastFrameWasRendered || forceClear)
+ {
+ DALI_LOG_INFO(gLogFilter, Debug::General, "Render: Processing\n");
+
+ // Upload the geometries
+ for(auto&& geom : mImpl->geometryContainer)
+ {
+ geom->Upload(mImpl->graphicsController);
+ }
+ }
+}
+
+void RenderManager::PreRender(Integration::Scene& scene, std::vector<Rect<int>>& damagedRects)
+{
+ if(mImpl->partialUpdateAvailable != Integration::PartialUpdateAvailable::TRUE)
{
- DALI_LOG_INFO( gLogFilter, Debug::General, "Render: Processing\n" );
+ return;
+ }
+
+ Internal::Scene& sceneInternal = GetImplementation(scene);
+ SceneGraph::Scene* sceneObject = sceneInternal.GetSceneObject();
- if ( !uploadOnly )
+ if(sceneObject->IsRenderingSkipped())
+ {
+ // We don't need to calculate dirty rects
+ return;
+ }
+
+ class DamagedRectsCleaner
+ {
+ public:
+ explicit DamagedRectsCleaner(std::vector<Rect<int>>& damagedRects)
+ : mDamagedRects(damagedRects),
+ mCleanOnReturn(true)
{
- // Mark that we will require a post-render step to be performed (includes swap-buffers).
- status.SetNeedsPostRender( true );
}
- // Switch to the shared context
- if ( mImpl->currentContext != &mImpl->context )
+ void SetCleanOnReturn(bool cleanOnReturn)
{
- mImpl->currentContext = &mImpl->context;
+ mCleanOnReturn = cleanOnReturn;
+ }
- if ( mImpl->currentContext->IsSurfacelessContextSupported() )
+ ~DamagedRectsCleaner()
+ {
+ if(mCleanOnReturn)
{
- mImpl->glContextHelperAbstraction.MakeSurfacelessContextCurrent();
+ mDamagedRects.clear();
}
+ }
+
+ private:
+ std::vector<Rect<int>>& mDamagedRects;
+ bool mCleanOnReturn;
+ };
+
+ Rect<int32_t> surfaceRect = sceneObject->GetSurfaceRect();
+
+ // Clean collected dirty/damaged rects on exit if 3d layer or 3d node or other conditions.
+ DamagedRectsCleaner damagedRectCleaner(damagedRects);
+
+ // Mark previous dirty rects in the sorted array. The array is already sorted by node and renderer, frame number.
+ // so you don't need to sort: std::stable_sort(itemsDirtyRects.begin(), itemsDirtyRects.end());
+ std::vector<DirtyRect>& itemsDirtyRects = sceneInternal.GetItemsDirtyRects();
+ for(DirtyRect& dirtyRect : itemsDirtyRects)
+ {
+ dirtyRect.visited = false;
+ }
+
+ uint32_t instructionCount = sceneObject->GetRenderInstructions().Count(mImpl->renderBufferIndex);
+ for(uint32_t i = 0; i < instructionCount; ++i)
+ {
+ RenderInstruction& instruction = sceneObject->GetRenderInstructions().At(mImpl->renderBufferIndex, i);
- // Clear the current cached program when the context is switched
- mImpl->programController.ClearCurrentProgram();
+ if(instruction.mFrameBuffer)
+ {
+ return; // TODO: reset, we don't deal with render tasks with framebuffers (for now)
}
- // Upload the geometries
- for( uint32_t i = 0; i < mImpl->sceneContainer.size(); ++i )
+ const Camera* camera = instruction.GetCamera();
+ if(camera->mType == Camera::DEFAULT_TYPE && camera->mTargetPosition == Camera::DEFAULT_TARGET_POSITION)
{
- RenderInstructionContainer& instructions = mImpl->sceneContainer[i]->GetRenderInstructions();
- for ( uint32_t j = 0; j < instructions.Count( mImpl->renderBufferIndex ); ++j )
+ const Node* node = instruction.GetCamera()->GetNode();
+ if(node)
{
- RenderInstruction& instruction = instructions.At( mImpl->renderBufferIndex, j );
-
- const Matrix* viewMatrix = instruction.GetViewMatrix( mImpl->renderBufferIndex );
- const Matrix* projectionMatrix = instruction.GetProjectionMatrix( mImpl->renderBufferIndex );
+ Vector3 position;
+ Vector3 scale;
+ Quaternion orientation;
+ node->GetWorldMatrix(mImpl->renderBufferIndex).GetTransformComponents(position, orientation, scale);
+
+ Vector3 orientationAxis;
+ Radian orientationAngle;
+ orientation.ToAxisAngle(orientationAxis, orientationAngle);
+
+ if(position.x > Math::MACHINE_EPSILON_10000 ||
+ position.y > Math::MACHINE_EPSILON_10000 ||
+ orientationAxis != Vector3(0.0f, 1.0f, 0.0f) ||
+ orientationAngle != ANGLE_180 ||
+ scale != Vector3(1.0f, 1.0f, 1.0f))
+ {
+ return;
+ }
+ }
+ }
+ else
+ {
+ return;
+ }
- DALI_ASSERT_DEBUG( viewMatrix );
- DALI_ASSERT_DEBUG( projectionMatrix );
+ Rect<int32_t> viewportRect;
+ if(instruction.mIsViewportSet)
+ {
+ const int32_t y = (surfaceRect.height - instruction.mViewport.height) - instruction.mViewport.y;
+ viewportRect.Set(instruction.mViewport.x, y, instruction.mViewport.width, instruction.mViewport.height);
+ if(viewportRect.IsEmpty() || !viewportRect.IsValid())
+ {
+ return; // just skip funny use cases for now, empty viewport means it is set somewhere else
+ }
+ }
+ else
+ {
+ viewportRect = surfaceRect;
+ }
- if( viewMatrix && projectionMatrix )
+ const Matrix* viewMatrix = instruction.GetViewMatrix(mImpl->renderBufferIndex);
+ const Matrix* projectionMatrix = instruction.GetProjectionMatrix(mImpl->renderBufferIndex);
+ if(viewMatrix && projectionMatrix)
+ {
+ const RenderListContainer::SizeType count = instruction.RenderListCount();
+ for(RenderListContainer::SizeType index = 0u; index < count; ++index)
+ {
+ const RenderList* renderList = instruction.GetRenderList(index);
+ if(renderList && !renderList->IsEmpty())
{
- const RenderListContainer::SizeType renderListCount = instruction.RenderListCount();
-
- // Iterate through each render list.
- for( RenderListContainer::SizeType index = 0; index < renderListCount; ++index )
+ const std::size_t listCount = renderList->Count();
+ for(uint32_t listIndex = 0u; listIndex < listCount; ++listIndex)
{
- const RenderList* renderList = instruction.GetRenderList( index );
+ RenderItem& item = renderList->GetItem(listIndex);
+ // If the item does 3D transformation, do early exit and clean the damaged rect array
+ if(item.mUpdateSize == Vector3::ZERO)
+ {
+ return;
+ }
- if( renderList && !renderList->IsEmpty() )
+ Rect<int> rect;
+ DirtyRect dirtyRect(item.mNode, item.mRenderer, mImpl->frameCount, rect);
+ // If the item refers to updated node or renderer.
+ if(item.mIsUpdated ||
+ (item.mNode &&
+ (item.mNode->Updated() || (item.mRenderer && item.mRenderer->Updated(mImpl->renderBufferIndex, item.mNode)))))
+ {
+ item.mIsUpdated = false;
+ item.mNode->SetUpdatedTree(false);
+
+ rect = RenderItem::CalculateViewportSpaceAABB(item.mModelViewMatrix, item.mUpdateSize, viewportRect.width, viewportRect.height);
+ if(rect.IsValid() && rect.Intersect(viewportRect) && !rect.IsEmpty())
+ {
+ const int left = rect.x;
+ const int top = rect.y;
+ const int right = rect.x + rect.width;
+ const int bottom = rect.y + rect.height;
+ rect.x = (left / 16) * 16;
+ rect.y = (top / 16) * 16;
+ rect.width = ((right + 16) / 16) * 16 - rect.x;
+ rect.height = ((bottom + 16) / 16) * 16 - rect.y;
+
+ // Found valid dirty rect.
+ // 1. Insert it in the sorted array of the dirty rects.
+ // 2. Mark the related dirty rects as visited so they will not be removed below.
+ // 3. Keep only last 3 dirty rects for the same node and renderer (Tizen uses 3 back buffers, Ubuntu 1).
+ dirtyRect.rect = rect;
+ auto dirtyRectPos = std::lower_bound(itemsDirtyRects.begin(), itemsDirtyRects.end(), dirtyRect);
+ dirtyRectPos = itemsDirtyRects.insert(dirtyRectPos, dirtyRect);
+
+ int c = 1;
+ while(++dirtyRectPos != itemsDirtyRects.end())
+ {
+ if(dirtyRectPos->node != item.mNode || dirtyRectPos->renderer != item.mRenderer)
+ {
+ break;
+ }
+
+ dirtyRectPos->visited = true;
+ Rect<int>& dirtRect = dirtyRectPos->rect;
+ rect.Merge(dirtRect);
+
+ c++;
+ if(c > 3) // no more then 3 previous rects
+ {
+ itemsDirtyRects.erase(dirtyRectPos);
+ break;
+ }
+ }
+
+ damagedRects.push_back(rect);
+ }
+ }
+ else
{
- const std::size_t itemCount = renderList->Count();
- for( uint32_t itemIndex = 0u; itemIndex < itemCount; ++itemIndex )
+ // 1. The item is not dirty, the node and renderer referenced by the item are still exist.
+ // 2. Mark the related dirty rects as visited so they will not be removed below.
+ auto dirtyRectPos = std::lower_bound(itemsDirtyRects.begin(), itemsDirtyRects.end(), dirtyRect);
+ while(dirtyRectPos != itemsDirtyRects.end())
{
- const RenderItem& item = renderList->GetItem( itemIndex );
- if( DALI_LIKELY( item.mRenderer ) )
+ if(dirtyRectPos->node != item.mNode || dirtyRectPos->renderer != item.mRenderer)
{
- item.mRenderer->Upload( *mImpl->currentContext );
+ break;
}
+
+ dirtyRectPos->visited = true;
+ dirtyRectPos++;
}
}
}
}
}
}
+
+ // Check removed nodes or removed renderers dirty rects
+ auto i = itemsDirtyRects.begin();
+ auto j = itemsDirtyRects.begin();
+ while(i != itemsDirtyRects.end())
+ {
+ if(i->visited)
+ {
+ *j++ = *i;
+ }
+ else
+ {
+ Rect<int>& dirtRect = i->rect;
+ damagedRects.push_back(dirtRect);
+ }
+ i++;
+ }
+
+ itemsDirtyRects.resize(j - itemsDirtyRects.begin());
+ damagedRectCleaner.SetCleanOnReturn(false);
}
+void RenderManager::RenderScene(Integration::RenderStatus& status, Integration::Scene& scene, bool renderToFbo)
+{
+ Rect<int> clippingRect;
+ RenderScene(status, scene, renderToFbo, clippingRect);
+}
-void RenderManager::RenderScene( Integration::Scene& scene, bool renderToFbo )
+void RenderManager::RenderScene(Integration::RenderStatus& status, Integration::Scene& scene, bool renderToFbo, Rect<int>& clippingRect)
{
- Internal::Scene& sceneInternal = GetImplementation( scene );
- SceneGraph::Scene* sceneObject = sceneInternal.GetSceneObject();
+ // Reset main algorithms command buffer
+ mImpl->renderAlgorithms.ResetCommandBuffer();
+
+ auto mainCommandBuffer = mImpl->renderAlgorithms.GetMainCommandBuffer();
- uint32_t count = sceneObject->GetRenderInstructions().Count( mImpl->renderBufferIndex );
+ Internal::Scene& sceneInternal = GetImplementation(scene);
+ SceneGraph::Scene* sceneObject = sceneInternal.GetSceneObject();
- for( uint32_t i = 0; i < count; ++i )
+ uint32_t count = sceneObject->GetRenderInstructions().Count(mImpl->renderBufferIndex);
+
+ std::vector<Graphics::RenderTarget*> targetstoPresent;
+
+ for(uint32_t i = 0; i < count; ++i)
{
- RenderInstruction& instruction = sceneObject->GetRenderInstructions().At( mImpl->renderBufferIndex, i );
+ RenderInstruction& instruction = sceneObject->GetRenderInstructions().At(mImpl->renderBufferIndex, i);
- if ( ( renderToFbo && !instruction.mFrameBuffer ) || ( !renderToFbo && instruction.mFrameBuffer ) )
+ if((renderToFbo && !instruction.mFrameBuffer) || (!renderToFbo && instruction.mFrameBuffer))
{
continue; // skip
}
+ // Mark that we will require a post-render step to be performed (includes swap-buffers).
+ status.SetNeedsPostRender(true);
+
Rect<int32_t> viewportRect;
- Vector4 clearColor;
- if ( instruction.mIsClearColorSet )
- {
- clearColor = instruction.mClearColor;
- }
- else
- {
- clearColor = Dali::RenderTask::DEFAULT_CLEAR_COLOR;
- }
+ Rect<int32_t> surfaceRect = sceneObject->GetSurfaceRect();
+ int32_t surfaceOrientation = sceneObject->GetSurfaceOrientation();
- Rect<int32_t> surfaceRect = mImpl->defaultSurfaceRect;
- Integration::DepthBufferAvailable depthBufferAvailable = mImpl->depthBufferAvailable;
+ // @todo Should these be part of scene?
+ Integration::DepthBufferAvailable depthBufferAvailable = mImpl->depthBufferAvailable;
Integration::StencilBufferAvailable stencilBufferAvailable = mImpl->stencilBufferAvailable;
- if ( instruction.mFrameBuffer )
+ Graphics::RenderTarget* currentRenderTarget = nullptr;
+ Graphics::RenderPass* currentRenderPass = nullptr;
+ std::vector<Graphics::ClearValue> currentClearValues{};
+
+ if(instruction.mFrameBuffer)
{
- // offscreen buffer
- if ( mImpl->currentContext != &mImpl->context )
+ // Ensure graphics framebuffer is created, bind attachments and create render passes
+ // Only happens once per framebuffer. If the create fails, e.g. no attachments yet,
+ // then don't render to this framebuffer.
+ if(!instruction.mFrameBuffer->GetGraphicsObject())
{
- // Switch to shared context for off-screen buffer
- mImpl->currentContext = &mImpl->context;
-
- if ( mImpl->currentContext->IsSurfacelessContextSupported() )
+ const bool created = instruction.mFrameBuffer->CreateGraphicsObjects();
+ if(!created)
{
- mImpl->glContextHelperAbstraction.MakeSurfacelessContextCurrent();
+ continue;
}
+ }
+
+ auto& clearValues = instruction.mFrameBuffer->GetGraphicsRenderPassClearValues();
- // Clear the current cached program when the context is switched
- mImpl->programController.ClearCurrentProgram();
+ // Set the clear color for first color attachment
+ if(instruction.mIsClearColorSet && !clearValues.empty())
+ {
+ clearValues[0].color = {
+ instruction.mClearColor.r,
+ instruction.mClearColor.g,
+ instruction.mClearColor.b,
+ instruction.mClearColor.a};
}
+
+ currentClearValues = clearValues;
+
+ auto loadOp = instruction.mIsClearColorSet ? Graphics::AttachmentLoadOp::CLEAR : Graphics::AttachmentLoadOp::LOAD;
+
+ // offscreen buffer
+ currentRenderTarget = instruction.mFrameBuffer->GetGraphicsRenderTarget();
+ currentRenderPass = instruction.mFrameBuffer->GetGraphicsRenderPass(loadOp, Graphics::AttachmentStoreOp::STORE);
}
- else
+ else // no framebuffer
{
- if ( mImpl->currentContext->IsSurfacelessContextSupported() )
+ // surface
+ auto& clearValues = sceneObject->GetGraphicsRenderPassClearValues();
+
+ if(instruction.mIsClearColorSet)
{
- if ( mImpl->currentContext != sceneObject->GetContext() )
- {
- // Switch the correct context if rendering to a surface
- mImpl->currentContext = sceneObject->GetContext();
+ clearValues[0].color = {
+ instruction.mClearColor.r,
+ instruction.mClearColor.g,
+ instruction.mClearColor.b,
+ instruction.mClearColor.a};
+ }
- // Clear the current cached program when the context is switched
- mImpl->programController.ClearCurrentProgram();
- }
+ currentClearValues = clearValues;
+
+ // @todo SceneObject should already have the depth clear / stencil clear in the clearValues array.
+ // if the window has a depth/stencil buffer.
+ if((depthBufferAvailable == Integration::DepthBufferAvailable::TRUE ||
+ stencilBufferAvailable == Integration::StencilBufferAvailable::TRUE) &&
+ (currentClearValues.size() <= 1))
+ {
+ currentClearValues.emplace_back();
+ currentClearValues.back().depthStencil.depth = 0;
+ currentClearValues.back().depthStencil.stencil = 0;
}
- surfaceRect = Rect<int32_t>( 0, 0, static_cast<int32_t>( scene.GetSize().width ), static_cast<int32_t>( scene.GetSize().height ) );
+ auto loadOp = instruction.mIsClearColorSet ? Graphics::AttachmentLoadOp::CLEAR : Graphics::AttachmentLoadOp::LOAD;
+
+ currentRenderTarget = sceneObject->GetSurfaceRenderTarget();
+ currentRenderPass = sceneObject->GetGraphicsRenderPass(loadOp, Graphics::AttachmentStoreOp::STORE);
}
- DALI_ASSERT_DEBUG( mImpl->currentContext->IsGlContextCreated() );
+ targetstoPresent.emplace_back(currentRenderTarget);
// reset the program matrices for all programs once per frame
// this ensures we will set view and projection matrix once per program per camera
mImpl->programController.ResetProgramMatrices();
- if( instruction.mFrameBuffer )
+ if(instruction.mFrameBuffer)
{
- instruction.mFrameBuffer->Bind( *mImpl->currentContext );
-
// For each offscreen buffer, update the dependency list with the new texture id used by this frame buffer.
- for (unsigned int i0 = 0, i1 = instruction.mFrameBuffer->GetColorAttachmentCount(); i0 < i1; ++i0)
+ for(unsigned int i0 = 0, i1 = instruction.mFrameBuffer->GetColorAttachmentCount(); i0 < i1; ++i0)
{
- mImpl->textureDependencyList.PushBack( instruction.mFrameBuffer->GetTextureId(i0) );
+ mImpl->textureDependencyList.PushBack(instruction.mFrameBuffer->GetTexture(i0));
}
}
- else
- {
- mImpl->currentContext->BindFramebuffer( GL_FRAMEBUFFER, 0u );
- }
-
- if ( !instruction.mFrameBuffer )
- {
- mImpl->currentContext->Viewport( surfaceRect.x,
- surfaceRect.y,
- surfaceRect.width,
- surfaceRect.height );
- }
-
- // Clear the entire color, depth and stencil buffers for the default framebuffer, if required.
- // It is important to clear all 3 buffers when they are being used, for performance on deferred renderers
- // e.g. previously when the depth & stencil buffers were NOT cleared, it caused the DDK to exceed a "vertex count limit",
- // and then stall. That problem is only noticeable when rendering a large number of vertices per frame.
- GLbitfield clearMask = GL_COLOR_BUFFER_BIT;
-
- mImpl->currentContext->ColorMask( true );
-
- if( depthBufferAvailable == Integration::DepthBufferAvailable::TRUE )
- {
- mImpl->currentContext->DepthMask( true );
- clearMask |= GL_DEPTH_BUFFER_BIT;
- }
-
- if( stencilBufferAvailable == Integration::StencilBufferAvailable::TRUE)
- {
- mImpl->currentContext->ClearStencil( 0 );
- mImpl->currentContext->StencilMask( 0xFF ); // 8 bit stencil mask, all 1's
- clearMask |= GL_STENCIL_BUFFER_BIT;
- }
- if( !instruction.mIgnoreRenderToFbo && ( instruction.mFrameBuffer != 0 ) )
+ if(!instruction.mIgnoreRenderToFbo && (instruction.mFrameBuffer != nullptr))
{
// Offscreen buffer rendering
- if ( instruction.mIsViewportSet )
+ if(instruction.mIsViewportSet)
{
- // For glViewport the lower-left corner is (0,0)
- const int32_t y = ( instruction.mFrameBuffer->GetHeight() - instruction.mViewport.height ) - instruction.mViewport.y;
- viewportRect.Set( instruction.mViewport.x, y, instruction.mViewport.width, instruction.mViewport.height );
+ // For Viewport the lower-left corner is (0,0)
+ const int32_t y = (instruction.mFrameBuffer->GetHeight() - instruction.mViewport.height) - instruction.mViewport.y;
+ viewportRect.Set(instruction.mViewport.x, y, instruction.mViewport.width, instruction.mViewport.height);
}
else
{
- viewportRect.Set( 0, 0, instruction.mFrameBuffer->GetWidth(), instruction.mFrameBuffer->GetHeight() );
+ viewportRect.Set(0, 0, instruction.mFrameBuffer->GetWidth(), instruction.mFrameBuffer->GetHeight());
}
+ surfaceOrientation = 0;
}
else // No Offscreen frame buffer rendering
{
// Check whether a viewport is specified, otherwise the full surface size is used
- if ( instruction.mIsViewportSet )
+ if(instruction.mIsViewportSet)
{
- // For glViewport the lower-left corner is (0,0)
- const int32_t y = ( surfaceRect.height - instruction.mViewport.height ) - instruction.mViewport.y;
- viewportRect.Set( instruction.mViewport.x, y, instruction.mViewport.width, instruction.mViewport.height );
+ // For Viewport the lower-left corner is (0,0)
+ const int32_t y = (surfaceRect.height - instruction.mViewport.height) - instruction.mViewport.y;
+ viewportRect.Set(instruction.mViewport.x, y, instruction.mViewport.width, instruction.mViewport.height);
}
else
{
}
}
- bool clearFullFrameRect = true;
- if( instruction.mFrameBuffer != 0 )
- {
- Viewport frameRect( 0, 0, instruction.mFrameBuffer->GetWidth(), instruction.mFrameBuffer->GetHeight() );
- clearFullFrameRect = ( frameRect == viewportRect );
- }
- else
+ // Set surface orientation
+ // @todo Inform graphics impl by another route.
+ // was: mImpl->currentContext->SetSurfaceOrientation(surfaceOrientation);
+
+ /*** Clear region of framebuffer or surface before drawing ***/
+ bool clearFullFrameRect = (surfaceRect == viewportRect);
+ if(instruction.mFrameBuffer != nullptr)
{
- clearFullFrameRect = ( surfaceRect == viewportRect );
+ Viewport frameRect(0, 0, instruction.mFrameBuffer->GetWidth(), instruction.mFrameBuffer->GetHeight());
+ clearFullFrameRect = (frameRect == viewportRect);
}
- mImpl->currentContext->Viewport(viewportRect.x, viewportRect.y, viewportRect.width, viewportRect.height);
-
- if( instruction.mIsClearColorSet )
+ if(!clippingRect.IsEmpty())
{
- mImpl->currentContext->ClearColor( clearColor.r,
- clearColor.g,
- clearColor.b,
- clearColor.a );
-
- if( !clearFullFrameRect )
- {
- mImpl->currentContext->SetScissorTest( true );
- mImpl->currentContext->Scissor( viewportRect.x, viewportRect.y, viewportRect.width, viewportRect.height );
- mImpl->currentContext->Clear( clearMask, Context::FORCE_CLEAR );
- mImpl->currentContext->SetScissorTest( false );
- }
- else
+ if(!clippingRect.Intersect(viewportRect))
{
- mImpl->currentContext->SetScissorTest( false );
- mImpl->currentContext->Clear( clearMask, Context::FORCE_CLEAR );
+ DALI_LOG_ERROR("Invalid clipping rect %d %d %d %d\n", clippingRect.x, clippingRect.y, clippingRect.width, clippingRect.height);
+ clippingRect = Rect<int>();
}
+ clearFullFrameRect = false;
}
- // Clear the list of bound textures
- mImpl->boundTextures.Clear();
-
- mImpl->renderAlgorithms.ProcessRenderInstruction(
- instruction,
- *mImpl->currentContext,
- mImpl->renderBufferIndex,
- depthBufferAvailable,
- stencilBufferAvailable,
- mImpl->boundTextures );
-
- // Synchronise the FBO/Texture access when there are multiple contexts
- if ( mImpl->currentContext->IsSurfacelessContextSupported() )
+ Graphics::Rect2D scissorArea{viewportRect.x, viewportRect.y, uint32_t(viewportRect.width), uint32_t(viewportRect.height)};
+ if(instruction.mIsClearColorSet)
{
- // Check whether any binded texture is in the dependency list
- bool textureFound = false;
-
- if ( mImpl->boundTextures.Count() > 0u && mImpl->textureDependencyList.Count() > 0u )
+ if(!clearFullFrameRect)
{
- for ( auto textureId : mImpl->textureDependencyList )
+ if(!clippingRect.IsEmpty())
{
-
- textureFound = std::find_if( mImpl->boundTextures.Begin(), mImpl->boundTextures.End(),
- [textureId]( GLuint id )
- {
- return textureId == id;
- } ) != mImpl->boundTextures.End();
+ scissorArea = {clippingRect.x, clippingRect.y, uint32_t(clippingRect.width), uint32_t(clippingRect.height)};
}
}
+ }
- if ( textureFound )
- {
- if ( instruction.mFrameBuffer )
- {
- // For off-screen buffer
-
- // Wait until all rendering calls for the currently context are executed
- mImpl->glContextHelperAbstraction.WaitClient();
-
- // Clear the dependency list
- mImpl->textureDependencyList.Clear();
- }
- else
- {
- // Worker thread lambda function
- auto& glContextHelperAbstraction = mImpl->glContextHelperAbstraction;
- auto workerFunction = [&glContextHelperAbstraction]( int workerThread )
- {
- // Switch to the shared context in the worker thread
- glContextHelperAbstraction.MakeSurfacelessContextCurrent();
-
- // Wait until all rendering calls for the shared context are executed
- glContextHelperAbstraction.WaitClient();
+ // Scissor's value should be set based on the default system coordinates.
+ // When the surface is rotated, the input values already were set with the rotated angle.
+ // So, re-calculation is needed.
+ scissorArea = RecalculateScissorArea(scissorArea, surfaceOrientation, viewportRect);
- // Must clear the context in the worker thread
- // Otherwise the shared context cannot be switched to from the render thread
- glContextHelperAbstraction.MakeContextNull();
- };
+ // Begin render pass
+ mainCommandBuffer->BeginRenderPass(
+ currentRenderPass,
+ currentRenderTarget,
+ scissorArea,
+ currentClearValues);
- auto future = mImpl->threadPool->SubmitTask( 0u, workerFunction );
- if ( future )
- {
- mImpl->threadPool->Wait();
+ mainCommandBuffer->SetViewport({float(viewportRect.x),
+ float(viewportRect.y),
+ float(viewportRect.width),
+ float(viewportRect.height)});
- // Clear the dependency list
- mImpl->textureDependencyList.Clear();
- }
- }
- }
- }
-
- if( instruction.mRenderTracker && instruction.mFrameBuffer )
- {
- // This will create a sync object every frame this render tracker
- // is alive (though it should be now be created only for
- // render-once render tasks)
- instruction.mRenderTracker->CreateSyncObject( mImpl->glSyncAbstraction );
- instruction.mRenderTracker = nullptr; // Only create once.
- }
+ // Clear the list of bound textures
+ mImpl->boundTextures.Clear();
- if ( renderToFbo )
+ mImpl->renderAlgorithms.ProcessRenderInstruction(
+ instruction,
+ mImpl->renderBufferIndex,
+ depthBufferAvailable,
+ stencilBufferAvailable,
+ mImpl->boundTextures,
+ viewportRect,
+ clippingRect,
+ surfaceOrientation);
+
+ Graphics::SyncObject* syncObject{nullptr};
+ // If the render instruction has an associated render tracker (owned separately)
+ // and framebuffer, create a one shot sync object, and use it to determine when
+ // the render pass has finished executing on GPU.
+ if(instruction.mRenderTracker && instruction.mFrameBuffer)
{
- mImpl->currentContext->Flush();
+ syncObject = instruction.mRenderTracker->CreateSyncObject(mImpl->graphicsController);
+ instruction.mRenderTracker = nullptr;
}
+ mainCommandBuffer->EndRenderPass(syncObject);
}
+ mImpl->renderAlgorithms.SubmitCommandBuffer();
- GLenum attachments[] = { GL_DEPTH, GL_STENCIL };
- mImpl->currentContext->InvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments);
-}
+ std::sort(targetstoPresent.begin(), targetstoPresent.end());
-void RenderManager::PostRender( bool uploadOnly )
-{
- if ( !uploadOnly )
+ Graphics::RenderTarget* rt = nullptr;
+ for(auto& target : targetstoPresent)
{
- if ( mImpl->currentContext->IsSurfacelessContextSupported() )
+ if(target != rt)
{
- mImpl->glContextHelperAbstraction.MakeSurfacelessContextCurrent();
+ mImpl->graphicsController.PresentRenderTarget(target);
+ rt = target;
}
-
- GLenum attachments[] = { GL_DEPTH, GL_STENCIL };
- mImpl->context.InvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments);
}
+}
- //Notify RenderGeometries that rendering has finished
- for ( auto&& iter : mImpl->geometryContainer )
+void RenderManager::PostRender(bool uploadOnly)
+{
+ // Notify RenderGeometries that rendering has finished
+ for(auto&& iter : mImpl->geometryContainer)
{
iter->OnRenderFinished();
}
mImpl->UpdateTrackers();
-
uint32_t count = 0u;
- for( uint32_t i = 0; i < mImpl->sceneContainer.size(); ++i )
+ for(auto& scene : mImpl->sceneContainer)
{
- count += mImpl->sceneContainer[i]->GetRenderInstructions().Count( mImpl->renderBufferIndex );
+ count += scene->GetRenderInstructions().Count(mImpl->renderBufferIndex);
}
const bool haveInstructions = count > 0u;