Added RenderPass and RenderTarget support
[platform/core/uifw/dali-core.git] / dali / internal / render / common / render-manager.cpp
1 /*
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/internal/render/common/render-manager.h>
20
21 // EXTERNAL INCLUDES
22 #include <memory.h>
23
24 // INTERNAL INCLUDES
25 #include <dali/devel-api/threading/thread-pool.h>
26 #include <dali/integration-api/core.h>
27 #include <dali/integration-api/gl-context-helper-abstraction.h>
28
29 #include <dali/internal/event/common/scene-impl.h>
30
31 #include <dali/internal/update/common/scene-graph-scene.h>
32 #include <dali/internal/update/render-tasks/scene-graph-camera.h>
33
34 #include <dali/internal/render/common/render-algorithms.h>
35 #include <dali/internal/render/common/render-debug.h>
36 #include <dali/internal/render/common/render-instruction.h>
37 #include <dali/internal/render/common/render-tracker.h>
38 #include <dali/internal/render/queue/render-queue.h>
39 #include <dali/internal/render/renderers/render-frame-buffer.h>
40 #include <dali/internal/render/renderers/render-texture.h>
41 #include <dali/internal/render/renderers/shader-cache.h>
42 #include <dali/internal/render/renderers/uniform-buffer-manager.h>
43 #include <dali/internal/render/shaders/program-controller.h>
44
45 namespace Dali
46 {
47 namespace Internal
48 {
49 namespace SceneGraph
50 {
51 #if defined(DEBUG_ENABLED)
52 namespace
53 {
54 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RENDER_MANAGER");
55 } // unnamed namespace
56 #endif
57
58 /**
59  * Structure to contain internal data
60  */
61 struct RenderManager::Impl
62 {
63   Impl(Graphics::Controller&               graphicsController,
64        Integration::DepthBufferAvailable   depthBufferAvailableParam,
65        Integration::StencilBufferAvailable stencilBufferAvailableParam,
66        Integration::PartialUpdateAvailable partialUpdateAvailableParam)
67   : context(graphicsController.GetGlAbstraction(), &sceneContextContainer),
68     currentContext(&context),
69     graphicsController(graphicsController),
70     renderQueue(),
71     renderAlgorithms(graphicsController),
72     frameCount(0u),
73     renderBufferIndex(SceneGraphBuffers::INITIAL_UPDATE_BUFFER_INDEX),
74     rendererContainer(),
75     samplerContainer(),
76     textureContainer(),
77     frameBufferContainer(),
78     lastFrameWasRendered(false),
79     programController(graphicsController),
80     shaderCache(graphicsController),
81     depthBufferAvailable(depthBufferAvailableParam),
82     stencilBufferAvailable(stencilBufferAvailableParam),
83     partialUpdateAvailable(partialUpdateAvailableParam)
84   {
85     // Create thread pool with just one thread ( there may be a need to create more threads in the future ).
86     threadPool = std::unique_ptr<Dali::ThreadPool>(new Dali::ThreadPool());
87     threadPool->Initialize(1u);
88
89     uniformBufferManager.reset(new Render::UniformBufferManager(&graphicsController));
90
91     // initialize main command buffer
92     auto info = Graphics::CommandBufferCreateInfo().SetLevel( Graphics::CommandBufferLevel::PRIMARY );
93     mainCommandBuffer = graphicsController.CreateCommandBuffer( info, nullptr );
94   }
95
96   ~Impl()
97   {
98     threadPool.reset(nullptr); // reset now to maintain correct destruction order
99   }
100
101   void AddRenderTracker(Render::RenderTracker* renderTracker)
102   {
103     DALI_ASSERT_DEBUG(renderTracker != NULL);
104     mRenderTrackers.PushBack(renderTracker);
105   }
106
107   void RemoveRenderTracker(Render::RenderTracker* renderTracker)
108   {
109     mRenderTrackers.EraseObject(renderTracker);
110   }
111
112   Context* CreateSceneContext()
113   {
114     Context* context = new Context(graphicsController.GetGlAbstraction());
115     sceneContextContainer.PushBack(context);
116     return context;
117   }
118
119   void DestroySceneContext(Context* sceneContext)
120   {
121     auto iter = std::find(sceneContextContainer.Begin(), sceneContextContainer.End(), sceneContext);
122     if(iter != sceneContextContainer.End())
123     {
124       (*iter)->GlContextDestroyed();
125       sceneContextContainer.Erase(iter);
126     }
127   }
128
129   Context* ReplaceSceneContext(Context* oldSceneContext)
130   {
131     Context* newContext = new Context(graphicsController.GetGlAbstraction());
132
133     oldSceneContext->GlContextDestroyed();
134
135     std::replace(sceneContextContainer.begin(), sceneContextContainer.end(), oldSceneContext, newContext);
136     return newContext;
137   }
138
139   void UpdateTrackers()
140   {
141     for(auto&& iter : mRenderTrackers)
142     {
143       iter->PollSyncObject();
144     }
145   }
146
147   // the order is important for destruction,
148   // programs are owned by context at the moment.
149   Context                  context;               ///< Holds the GL state of the share resource context
150   Context*                 currentContext;        ///< Holds the GL state of the current context for rendering
151   OwnerContainer<Context*> sceneContextContainer; ///< List of owned contexts holding the GL state per scene
152   Graphics::Controller&    graphicsController;
153   RenderQueue              renderQueue; ///< A message queue for receiving messages from the update-thread.
154
155   std::vector<SceneGraph::Scene*> sceneContainer; ///< List of pointers to the scene graph objects of the scenes
156
157   Render::RenderAlgorithms renderAlgorithms; ///< The RenderAlgorithms object is used to action the renders required by a RenderInstruction
158
159   uint32_t    frameCount;        ///< The current frame count
160   BufferIndex renderBufferIndex; ///< The index of the buffer to read from; this is opposite of the "update" buffer
161
162   OwnerContainer<Render::Renderer*>     rendererContainer;     ///< List of owned renderers
163   OwnerContainer<Render::Sampler*>      samplerContainer;      ///< List of owned samplers
164   OwnerContainer<Render::Texture*>      textureContainer;      ///< List of owned textures
165   OwnerContainer<Render::FrameBuffer*>  frameBufferContainer;  ///< List of owned framebuffers
166   OwnerContainer<Render::VertexBuffer*> vertexBufferContainer; ///< List of owned vertex buffers
167   OwnerContainer<Render::Geometry*>     geometryContainer;     ///< List of owned Geometries
168
169   bool lastFrameWasRendered; ///< Keeps track of the last frame being rendered due to having render instructions
170
171   OwnerContainer<Render::RenderTracker*> mRenderTrackers; ///< List of render trackers
172
173   ProgramController   programController; ///< Owner of the GL programs
174   Render::ShaderCache shaderCache;       ///< The cache for the graphics shaders
175
176   std::unique_ptr<Render::UniformBufferManager> uniformBufferManager; ///< The uniform buffer manager
177
178   Integration::DepthBufferAvailable   depthBufferAvailable;   ///< Whether the depth buffer is available
179   Integration::StencilBufferAvailable stencilBufferAvailable; ///< Whether the stencil buffer is available
180   Integration::PartialUpdateAvailable partialUpdateAvailable; ///< Whether the partial update is available
181
182   std::unique_ptr<Dali::ThreadPool> threadPool;            ///< The thread pool
183   Vector<Graphics::Texture*>        boundTextures;         ///< The textures bound for rendering
184   Vector<Graphics::Texture*>        textureDependencyList; ///< The dependency list of binded textures
185
186   Graphics::UniquePtr<Graphics::CommandBuffer> mainCommandBuffer; ///< Main command buffer
187
188   Graphics::UniquePtr<Graphics::RenderPass> mainRenderPass; ///< Main renderpass
189
190
191 };
192
193 RenderManager* RenderManager::New(Graphics::Controller&               graphicsController,
194                                   Integration::DepthBufferAvailable   depthBufferAvailable,
195                                   Integration::StencilBufferAvailable stencilBufferAvailable,
196                                   Integration::PartialUpdateAvailable partialUpdateAvailable)
197 {
198   RenderManager* manager = new RenderManager;
199   manager->mImpl         = new Impl(graphicsController,
200                             depthBufferAvailable,
201                             stencilBufferAvailable,
202                             partialUpdateAvailable);
203   return manager;
204 }
205
206 RenderManager::RenderManager()
207 : mImpl(nullptr)
208 {
209 }
210
211 RenderManager::~RenderManager()
212 {
213   delete mImpl;
214 }
215
216 RenderQueue& RenderManager::GetRenderQueue()
217 {
218   return mImpl->renderQueue;
219 }
220
221 void RenderManager::ContextCreated()
222 {
223   mImpl->context.GlContextCreated();
224   mImpl->programController.GlContextCreated();
225
226   // renderers, textures and gpu buffers cannot reinitialize themselves
227   // so they rely on someone reloading the data for them
228 }
229
230 void RenderManager::ContextDestroyed()
231 {
232   mImpl->context.GlContextDestroyed();
233   mImpl->programController.GlContextDestroyed();
234
235   //Inform textures
236   for(auto&& texture : mImpl->textureContainer)
237   {
238     texture->Destroy();
239   }
240
241   //Inform framebuffers
242   for(auto&& framebuffer : mImpl->frameBufferContainer)
243   {
244     framebuffer->Destroy();
245   }
246
247   // inform renderers
248   for(auto&& renderer : mImpl->rendererContainer)
249   {
250     renderer->GlContextDestroyed();
251   }
252
253   // inform context
254   for(auto&& context : mImpl->sceneContextContainer)
255   {
256     context->GlContextDestroyed();
257   }
258 }
259
260 void RenderManager::SetShaderSaver(ShaderSaver& upstream)
261 {
262   mImpl->programController.SetShaderSaver(upstream);
263 }
264
265 void RenderManager::AddRenderer(OwnerPointer<Render::Renderer>& renderer)
266 {
267   // Initialize the renderer as we are now in render thread
268   renderer->Initialize(mImpl->context, mImpl->graphicsController, mImpl->programController, mImpl->shaderCache, *(mImpl->uniformBufferManager.get()));
269
270   mImpl->rendererContainer.PushBack(renderer.Release());
271 }
272
273 void RenderManager::RemoveRenderer(Render::Renderer* renderer)
274 {
275   mImpl->rendererContainer.EraseObject(renderer);
276 }
277
278 void RenderManager::AddSampler(OwnerPointer<Render::Sampler>& sampler)
279 {
280   sampler->Initialize(mImpl->graphicsController);
281   mImpl->samplerContainer.PushBack(sampler.Release());
282 }
283
284 void RenderManager::RemoveSampler(Render::Sampler* sampler)
285 {
286   mImpl->samplerContainer.EraseObject(sampler);
287 }
288
289 void RenderManager::AddTexture(OwnerPointer<Render::Texture>& texture)
290 {
291   texture->Initialize(mImpl->graphicsController);
292   mImpl->textureContainer.PushBack(texture.Release());
293 }
294
295 void RenderManager::RemoveTexture(Render::Texture* texture)
296 {
297   DALI_ASSERT_DEBUG(NULL != texture);
298
299   // Find the texture, use reference to pointer so we can do the erase safely
300   for(auto&& iter : mImpl->textureContainer)
301   {
302     if(iter == texture)
303     {
304       texture->Destroy();
305       mImpl->textureContainer.Erase(&iter); // Texture found; now destroy it
306       return;
307     }
308   }
309 }
310
311 void RenderManager::UploadTexture(Render::Texture* texture, PixelDataPtr pixelData, const Texture::UploadParams& params)
312 {
313   texture->Upload(pixelData, params);
314 }
315
316 void RenderManager::GenerateMipmaps(Render::Texture* texture)
317 {
318   texture->GenerateMipmaps();
319 }
320
321 void RenderManager::SetFilterMode(Render::Sampler* sampler, uint32_t minFilterMode, uint32_t magFilterMode)
322 {
323   sampler->SetFilterMode(static_cast<Dali::FilterMode::Type>(minFilterMode),
324                          static_cast<Dali::FilterMode::Type>(magFilterMode));
325 }
326
327 void RenderManager::SetWrapMode(Render::Sampler* sampler, uint32_t rWrapMode, uint32_t sWrapMode, uint32_t tWrapMode)
328 {
329   sampler->SetWrapMode(static_cast<Dali::WrapMode::Type>(rWrapMode),
330                        static_cast<Dali::WrapMode::Type>(sWrapMode),
331                        static_cast<Dali::WrapMode::Type>(tWrapMode));
332 }
333
334 void RenderManager::AddFrameBuffer(OwnerPointer<Render::FrameBuffer>& frameBuffer)
335 {
336   Render::FrameBuffer* frameBufferPtr = frameBuffer.Release();
337   mImpl->frameBufferContainer.PushBack(frameBufferPtr);
338   frameBufferPtr->Initialize(mImpl->graphicsController);
339 }
340
341 void RenderManager::RemoveFrameBuffer(Render::FrameBuffer* frameBuffer)
342 {
343   DALI_ASSERT_DEBUG(NULL != frameBuffer);
344
345   // Find the sampler, use reference so we can safely do the erase
346   for(auto&& iter : mImpl->frameBufferContainer)
347   {
348     if(iter == frameBuffer)
349     {
350       frameBuffer->Destroy();
351       mImpl->frameBufferContainer.Erase(&iter); // frameBuffer found; now destroy it
352
353       break;
354     }
355   }
356 }
357
358 void RenderManager::InitializeScene(SceneGraph::Scene* scene)
359 {
360   scene->Initialize(*mImpl->CreateSceneContext());
361   mImpl->sceneContainer.push_back(scene);
362 }
363
364 void RenderManager::UninitializeScene(SceneGraph::Scene* scene)
365 {
366   mImpl->DestroySceneContext(scene->GetContext());
367
368   auto iter = std::find(mImpl->sceneContainer.begin(), mImpl->sceneContainer.end(), scene);
369   if(iter != mImpl->sceneContainer.end())
370   {
371     mImpl->sceneContainer.erase(iter);
372   }
373 }
374
375 void RenderManager::SurfaceReplaced(SceneGraph::Scene* scene)
376 {
377   Context* newContext = mImpl->ReplaceSceneContext(scene->GetContext());
378   scene->Initialize(*newContext);
379 }
380
381 void RenderManager::AttachColorTextureToFrameBuffer(Render::FrameBuffer* frameBuffer, Render::Texture* texture, uint32_t mipmapLevel, uint32_t layer)
382 {
383   frameBuffer->AttachColorTexture(texture, mipmapLevel, layer);
384 }
385
386 void RenderManager::AttachDepthTextureToFrameBuffer(Render::FrameBuffer* frameBuffer, Render::Texture* texture, uint32_t mipmapLevel)
387 {
388   frameBuffer->AttachDepthTexture(texture, mipmapLevel);
389 }
390
391 void RenderManager::AttachDepthStencilTextureToFrameBuffer(Render::FrameBuffer* frameBuffer, Render::Texture* texture, uint32_t mipmapLevel)
392 {
393   frameBuffer->AttachDepthStencilTexture(texture, mipmapLevel);
394 }
395
396 void RenderManager::AddVertexBuffer(OwnerPointer<Render::VertexBuffer>& vertexBuffer)
397 {
398   mImpl->vertexBufferContainer.PushBack(vertexBuffer.Release());
399 }
400
401 void RenderManager::RemoveVertexBuffer(Render::VertexBuffer* vertexBuffer)
402 {
403   mImpl->vertexBufferContainer.EraseObject(vertexBuffer);
404 }
405
406 void RenderManager::SetVertexBufferFormat(Render::VertexBuffer* vertexBuffer, OwnerPointer<Render::VertexBuffer::Format>& format)
407 {
408   vertexBuffer->SetFormat(format.Release());
409 }
410
411 void RenderManager::SetVertexBufferData(Render::VertexBuffer* vertexBuffer, OwnerPointer<Vector<uint8_t>>& data, uint32_t size)
412 {
413   vertexBuffer->SetData(data.Release(), size);
414 }
415
416 void RenderManager::SetIndexBuffer(Render::Geometry* geometry, Dali::Vector<uint16_t>& indices)
417 {
418   geometry->SetIndexBuffer(indices);
419 }
420
421 void RenderManager::AddGeometry(OwnerPointer<Render::Geometry>& geometry)
422 {
423   mImpl->geometryContainer.PushBack(geometry.Release());
424 }
425
426 void RenderManager::RemoveGeometry(Render::Geometry* geometry)
427 {
428   mImpl->geometryContainer.EraseObject(geometry);
429 }
430
431 void RenderManager::AttachVertexBuffer(Render::Geometry* geometry, Render::VertexBuffer* vertexBuffer)
432 {
433   DALI_ASSERT_DEBUG(NULL != geometry);
434
435   // Find the geometry
436   for(auto&& iter : mImpl->geometryContainer)
437   {
438     if(iter == geometry)
439     {
440       iter->AddVertexBuffer(vertexBuffer);
441       break;
442     }
443   }
444 }
445
446 void RenderManager::RemoveVertexBuffer(Render::Geometry* geometry, Render::VertexBuffer* vertexBuffer)
447 {
448   DALI_ASSERT_DEBUG(NULL != geometry);
449
450   // Find the geometry
451   for(auto&& iter : mImpl->geometryContainer)
452   {
453     if(iter == geometry)
454     {
455       iter->RemoveVertexBuffer(vertexBuffer);
456       break;
457     }
458   }
459 }
460
461 void RenderManager::SetGeometryType(Render::Geometry* geometry, uint32_t geometryType)
462 {
463   geometry->SetType(Render::Geometry::Type(geometryType));
464 }
465
466 void RenderManager::AddRenderTracker(Render::RenderTracker* renderTracker)
467 {
468   mImpl->AddRenderTracker(renderTracker);
469 }
470
471 void RenderManager::RemoveRenderTracker(Render::RenderTracker* renderTracker)
472 {
473   mImpl->RemoveRenderTracker(renderTracker);
474 }
475
476 ProgramCache* RenderManager::GetProgramCache()
477 {
478   return &(mImpl->programController);
479 }
480
481 void RenderManager::PreRender(Integration::RenderStatus& status, bool forceClear, bool uploadOnly)
482 {
483   DALI_PRINT_RENDER_START(mImpl->renderBufferIndex);
484
485   // Core::Render documents that GL context must be current before calling Render
486   DALI_ASSERT_DEBUG(mImpl->context.IsGlContextCreated());
487
488   // Increment the frame count at the beginning of each frame
489   ++mImpl->frameCount;
490
491   // Process messages queued during previous update
492   mImpl->renderQueue.ProcessMessages(mImpl->renderBufferIndex);
493
494   uint32_t count = 0u;
495   for(uint32_t i = 0; i < mImpl->sceneContainer.size(); ++i)
496   {
497     count += mImpl->sceneContainer[i]->GetRenderInstructions().Count(mImpl->renderBufferIndex);
498   }
499
500   const bool haveInstructions = count > 0u;
501
502   // Reset main command buffer
503   mImpl->mainCommandBuffer->Reset();
504
505   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");
506
507   // Only render if we have instructions to render, or the last frame was rendered (and therefore a clear is required).
508   if(haveInstructions || mImpl->lastFrameWasRendered || forceClear)
509   {
510     DALI_LOG_INFO(gLogFilter, Debug::General, "Render: Processing\n");
511
512     // Switch to the shared context
513     if(mImpl->currentContext != &mImpl->context)
514     {
515       mImpl->currentContext = &mImpl->context;
516
517       if(mImpl->currentContext->IsSurfacelessContextSupported())
518       {
519         mImpl->graphicsController.GetGlContextHelperAbstraction().MakeSurfacelessContextCurrent();
520       }
521
522       // Clear the current cached program when the context is switched
523       mImpl->programController.ClearCurrentProgram();
524     }
525
526     // Upload the geometries
527     for(uint32_t i = 0; i < mImpl->sceneContainer.size(); ++i)
528     {
529       RenderInstructionContainer& instructions = mImpl->sceneContainer[i]->GetRenderInstructions();
530       for(uint32_t j = 0; j < instructions.Count(mImpl->renderBufferIndex); ++j)
531       {
532         RenderInstruction& instruction = instructions.At(mImpl->renderBufferIndex, j);
533
534         const Matrix* viewMatrix       = instruction.GetViewMatrix(mImpl->renderBufferIndex);
535         const Matrix* projectionMatrix = instruction.GetProjectionMatrix(mImpl->renderBufferIndex);
536
537         DALI_ASSERT_DEBUG(viewMatrix);
538         DALI_ASSERT_DEBUG(projectionMatrix);
539
540         if(viewMatrix && projectionMatrix)
541         {
542           const RenderListContainer::SizeType renderListCount = instruction.RenderListCount();
543
544           // Iterate through each render list.
545           for(RenderListContainer::SizeType index = 0; index < renderListCount; ++index)
546           {
547             const RenderList* renderList = instruction.GetRenderList(index);
548
549             if(renderList && !renderList->IsEmpty())
550             {
551               const std::size_t itemCount = renderList->Count();
552               for(uint32_t itemIndex = 0u; itemIndex < itemCount; ++itemIndex)
553               {
554                 const RenderItem& item = renderList->GetItem(itemIndex);
555                 if(DALI_LIKELY(item.mRenderer))
556                 {
557                   item.mRenderer->Upload();
558                 }
559               }
560             }
561           }
562         }
563       }
564     }
565   }
566 }
567
568 void RenderManager::PreRender(Integration::Scene& scene, std::vector<Rect<int>>& damagedRects)
569 {
570   if(mImpl->partialUpdateAvailable != Integration::PartialUpdateAvailable::TRUE)
571   {
572     return;
573   }
574
575   Internal::Scene&   sceneInternal = GetImplementation(scene);
576   SceneGraph::Scene* sceneObject   = sceneInternal.GetSceneObject();
577
578   if(sceneObject->IsRenderingSkipped())
579   {
580     // We don't need to calculate dirty rects
581     return;
582   }
583
584   class DamagedRectsCleaner
585   {
586   public:
587     DamagedRectsCleaner(std::vector<Rect<int>>& damagedRects)
588     : mDamagedRects(damagedRects),
589       mCleanOnReturn(true)
590     {
591     }
592
593     void SetCleanOnReturn(bool cleanOnReturn)
594     {
595       mCleanOnReturn = cleanOnReturn;
596     }
597
598     ~DamagedRectsCleaner()
599     {
600       if(mCleanOnReturn)
601       {
602         mDamagedRects.clear();
603       }
604     }
605
606   private:
607     std::vector<Rect<int>>& mDamagedRects;
608     bool                    mCleanOnReturn;
609   };
610
611   Rect<int32_t> surfaceRect = sceneObject->GetSurfaceRect();
612
613   // Clean collected dirty/damaged rects on exit if 3d layer or 3d node or other conditions.
614   DamagedRectsCleaner damagedRectCleaner(damagedRects);
615
616   // Mark previous dirty rects in the sorted array. The array is already sorted by node and renderer, frame number.
617   // so you don't need to sort: std::stable_sort(itemsDirtyRects.begin(), itemsDirtyRects.end());
618   std::vector<DirtyRect>& itemsDirtyRects = sceneInternal.GetItemsDirtyRects();
619   for(DirtyRect& dirtyRect : itemsDirtyRects)
620   {
621     dirtyRect.visited = false;
622   }
623
624   uint32_t count = sceneObject->GetRenderInstructions().Count(mImpl->renderBufferIndex);
625   for(uint32_t i = 0; i < count; ++i)
626   {
627     RenderInstruction& instruction = sceneObject->GetRenderInstructions().At(mImpl->renderBufferIndex, i);
628
629     if(instruction.mFrameBuffer)
630     {
631       return; // TODO: reset, we don't deal with render tasks with framebuffers (for now)
632     }
633
634     const Camera* camera = instruction.GetCamera();
635     if(camera->mType == Camera::DEFAULT_TYPE && camera->mTargetPosition == Camera::DEFAULT_TARGET_POSITION)
636     {
637       const Node* node = instruction.GetCamera()->GetNode();
638       if(node)
639       {
640         Vector3    position;
641         Vector3    scale;
642         Quaternion orientation;
643         node->GetWorldMatrix(mImpl->renderBufferIndex).GetTransformComponents(position, orientation, scale);
644
645         Vector3 orientationAxis;
646         Radian  orientationAngle;
647         orientation.ToAxisAngle(orientationAxis, orientationAngle);
648
649         if(position.x > Math::MACHINE_EPSILON_10000 ||
650            position.y > Math::MACHINE_EPSILON_10000 ||
651            orientationAxis != Vector3(0.0f, 1.0f, 0.0f) ||
652            orientationAngle != ANGLE_180 ||
653            scale != Vector3(1.0f, 1.0f, 1.0f))
654         {
655           return;
656         }
657       }
658     }
659     else
660     {
661       return;
662     }
663
664     Rect<int32_t> viewportRect;
665     if(instruction.mIsViewportSet)
666     {
667       const int32_t y = (surfaceRect.height - instruction.mViewport.height) - instruction.mViewport.y;
668       viewportRect.Set(instruction.mViewport.x, y, instruction.mViewport.width, instruction.mViewport.height);
669       if(viewportRect.IsEmpty() || !viewportRect.IsValid())
670       {
671         return; // just skip funny use cases for now, empty viewport means it is set somewhere else
672       }
673     }
674     else
675     {
676       viewportRect = surfaceRect;
677     }
678
679     const Matrix* viewMatrix       = instruction.GetViewMatrix(mImpl->renderBufferIndex);
680     const Matrix* projectionMatrix = instruction.GetProjectionMatrix(mImpl->renderBufferIndex);
681     if(viewMatrix && projectionMatrix)
682     {
683       const RenderListContainer::SizeType count = instruction.RenderListCount();
684       for(RenderListContainer::SizeType index = 0u; index < count; ++index)
685       {
686         const RenderList* renderList = instruction.GetRenderList(index);
687         if(renderList && !renderList->IsEmpty())
688         {
689           const std::size_t count = renderList->Count();
690           for(uint32_t index = 0u; index < count; ++index)
691           {
692             RenderItem& item = renderList->GetItem(index);
693             // If the item does 3D transformation, do early exit and clean the damaged rect array
694             if(item.mUpdateSize == Vector3::ZERO)
695             {
696               return;
697             }
698
699             Rect<int> rect;
700             DirtyRect dirtyRect(item.mNode, item.mRenderer, mImpl->frameCount, rect);
701             // If the item refers to updated node or renderer.
702             if(item.mIsUpdated ||
703                (item.mNode &&
704                 (item.mNode->Updated() || (item.mRenderer && item.mRenderer->Updated(mImpl->renderBufferIndex, item.mNode)))))
705             {
706               item.mIsUpdated = false;
707               item.mNode->SetUpdated(false);
708
709               rect = item.CalculateViewportSpaceAABB(item.mUpdateSize, viewportRect.width, viewportRect.height);
710               if(rect.IsValid() && rect.Intersect(viewportRect) && !rect.IsEmpty())
711               {
712                 const int left   = rect.x;
713                 const int top    = rect.y;
714                 const int right  = rect.x + rect.width;
715                 const int bottom = rect.y + rect.height;
716                 rect.x           = (left / 16) * 16;
717                 rect.y           = (top / 16) * 16;
718                 rect.width       = ((right + 16) / 16) * 16 - rect.x;
719                 rect.height      = ((bottom + 16) / 16) * 16 - rect.y;
720
721                 // Found valid dirty rect.
722                 // 1. Insert it in the sorted array of the dirty rects.
723                 // 2. Mark the related dirty rects as visited so they will not be removed below.
724                 // 3. Keep only last 3 dirty rects for the same node and renderer (Tizen uses 3 back buffers, Ubuntu 1).
725                 dirtyRect.rect    = rect;
726                 auto dirtyRectPos = std::lower_bound(itemsDirtyRects.begin(), itemsDirtyRects.end(), dirtyRect);
727                 dirtyRectPos      = itemsDirtyRects.insert(dirtyRectPos, dirtyRect);
728
729                 int c = 1;
730                 while(++dirtyRectPos != itemsDirtyRects.end())
731                 {
732                   if(dirtyRectPos->node != item.mNode || dirtyRectPos->renderer != item.mRenderer)
733                   {
734                     break;
735                   }
736
737                   dirtyRectPos->visited = true;
738                   Rect<int>& dirtRect   = dirtyRectPos->rect;
739                   rect.Merge(dirtRect);
740
741                   c++;
742                   if(c > 3) // no more then 3 previous rects
743                   {
744                     itemsDirtyRects.erase(dirtyRectPos);
745                     break;
746                   }
747                 }
748
749                 damagedRects.push_back(rect);
750               }
751             }
752             else
753             {
754               // 1. The item is not dirty, the node and renderer referenced by the item are still exist.
755               // 2. Mark the related dirty rects as visited so they will not be removed below.
756               auto dirtyRectPos = std::lower_bound(itemsDirtyRects.begin(), itemsDirtyRects.end(), dirtyRect);
757               while(dirtyRectPos != itemsDirtyRects.end())
758               {
759                 if(dirtyRectPos->node != item.mNode || dirtyRectPos->renderer != item.mRenderer)
760                 {
761                   break;
762                 }
763
764                 dirtyRectPos->visited = true;
765                 dirtyRectPos++;
766               }
767             }
768           }
769         }
770       }
771     }
772   }
773
774   // Check removed nodes or removed renderers dirty rects
775   auto i = itemsDirtyRects.begin();
776   auto j = itemsDirtyRects.begin();
777   while(i != itemsDirtyRects.end())
778   {
779     if(i->visited)
780     {
781       *j++ = *i;
782     }
783     else
784     {
785       Rect<int>& dirtRect = i->rect;
786       damagedRects.push_back(dirtRect);
787     }
788     i++;
789   }
790
791   itemsDirtyRects.resize(j - itemsDirtyRects.begin());
792   damagedRectCleaner.SetCleanOnReturn(false);
793 }
794
795 void RenderManager::RenderScene(Integration::RenderStatus& status, Integration::Scene& scene, bool renderToFbo)
796 {
797   Rect<int> clippingRect;
798   RenderScene(status, scene, renderToFbo, clippingRect);
799 }
800
801 void RenderManager::RenderScene(Integration::RenderStatus& status, Integration::Scene& scene, bool renderToFbo, Rect<int>& clippingRect)
802 {
803   // Reset main algorithms command buffer
804   mImpl->renderAlgorithms.ResetCommandBuffer();
805
806   auto mainCommandBuffer = mImpl->renderAlgorithms.GetMainCommandBuffer();
807
808   Internal::Scene&   sceneInternal = GetImplementation(scene);
809   SceneGraph::Scene* sceneObject   = sceneInternal.GetSceneObject();
810
811   uint32_t count = sceneObject->GetRenderInstructions().Count(mImpl->renderBufferIndex);
812
813   for(uint32_t i = 0; i < count; ++i)
814   {
815     RenderInstruction& instruction = sceneObject->GetRenderInstructions().At(mImpl->renderBufferIndex, i);
816
817     if((renderToFbo && !instruction.mFrameBuffer) || (!renderToFbo && instruction.mFrameBuffer))
818     {
819       continue; // skip
820     }
821
822     // Mark that we will require a post-render step to be performed (includes swap-buffers).
823     status.SetNeedsPostRender(true);
824
825     Rect<int32_t> viewportRect;
826     Vector4       clearColor;
827
828     if(instruction.mIsClearColorSet)
829     {
830       clearColor = instruction.mClearColor;
831     }
832     else
833     {
834       clearColor = Dali::RenderTask::DEFAULT_CLEAR_COLOR;
835     }
836
837     Rect<int32_t> surfaceRect        = sceneObject->GetSurfaceRect();
838     int32_t       surfaceOrientation = sceneObject->GetSurfaceOrientation();
839
840     Integration::DepthBufferAvailable   depthBufferAvailable   = mImpl->depthBufferAvailable;
841     Integration::StencilBufferAvailable stencilBufferAvailable = mImpl->stencilBufferAvailable;
842
843     if(instruction.mFrameBuffer)
844     {
845       auto& clearValues = instruction.mFrameBuffer->GetGraphicsRenderPassClearValues();
846       // todo: use no-clear renderpass instead (not implemented yet)
847
848       // Set the clear color for first color attachment
849       if( instruction.mIsClearColorSet )
850       {
851         clearValues[0].color = {
852           instruction.mClearColor.r,
853           instruction.mClearColor.g,
854           instruction.mClearColor.b,
855           instruction.mClearColor.a
856         };
857       }
858       // offscreen buffer
859       mainCommandBuffer->BeginRenderPass(
860         instruction.mFrameBuffer->GetGraphicsRenderPass( Graphics::AttachmentLoadOp::CLEAR, Graphics::AttachmentStoreOp::STORE ),
861         instruction.mFrameBuffer->GetGraphicsRenderTarget(),
862         { instruction.mFrameBuffer->GetWidth(), instruction.mFrameBuffer->GetHeight() },
863         clearValues
864         );
865
866       if(mImpl->currentContext != &mImpl->context)
867       {
868         // Switch to shared context for off-screen buffer
869         mImpl->currentContext = &mImpl->context;
870
871         if(mImpl->currentContext->IsSurfacelessContextSupported())
872         {
873           mImpl->graphicsController.GetGlContextHelperAbstraction().MakeSurfacelessContextCurrent();
874         }
875
876         // Clear the current cached program when the context is switched
877         mImpl->programController.ClearCurrentProgram();
878       }
879     }
880     else
881     {
882       if(mImpl->currentContext->IsSurfacelessContextSupported())
883       {
884         if(mImpl->currentContext != sceneObject->GetContext())
885         {
886           // Switch the correct context if rendering to a surface
887           mImpl->currentContext = sceneObject->GetContext();
888
889           // Clear the current cached program when the context is switched
890           mImpl->programController.ClearCurrentProgram();
891         }
892       }
893     }
894
895     // Make sure that GL context must be created
896     mImpl->currentContext->GlContextCreated();
897
898     // reset the program matrices for all programs once per frame
899     // this ensures we will set view and projection matrix once per program per camera
900     mImpl->programController.ResetProgramMatrices();
901
902     if(instruction.mFrameBuffer)
903     {
904
905       //instruction.mFrameBuffer->Bind(*mImpl->currentContext);
906       // @todo Temporarily set per renderer per pipeline. Should use RenderPass instead
907
908       // For each offscreen buffer, update the dependency list with the new texture id used by this frame buffer.
909       for(unsigned int i0 = 0, i1 = instruction.mFrameBuffer->GetColorAttachmentCount(); i0 < i1; ++i0)
910       {
911         mImpl->textureDependencyList.PushBack(instruction.mFrameBuffer->GetTexture(i0));
912       }
913     }
914     else
915     {
916       mImpl->currentContext->BindFramebuffer(GL_FRAMEBUFFER, 0u);
917     }
918
919     // @todo Should this be a command in it's own right?
920     // @todo yes
921     if(!instruction.mFrameBuffer)
922     {
923       mImpl->currentContext->Viewport(surfaceRect.x,
924                                       surfaceRect.y,
925                                       surfaceRect.width,
926                                       surfaceRect.height);
927       /*
928       mainCommandBuffer->SetViewport( {surfaceRect.x,
929                                         surfaceRect.y,
930                                         surfaceRect.width,
931                                         surfaceRect.height} );
932       */
933     }
934
935     // Clear the entire color, depth and stencil buffers for the default framebuffer, if required.
936     // It is important to clear all 3 buffers when they are being used, for performance on deferred renderers
937     // e.g. previously when the depth & stencil buffers were NOT cleared, it caused the DDK to exceed a "vertex count limit",
938     // and then stall. That problem is only noticeable when rendering a large number of vertices per frame.
939     GLbitfield clearMask = GL_COLOR_BUFFER_BIT;
940
941     mImpl->currentContext->ColorMask(true);
942
943     if(depthBufferAvailable == Integration::DepthBufferAvailable::TRUE)
944     {
945       mImpl->currentContext->DepthMask(true);
946       clearMask |= GL_DEPTH_BUFFER_BIT;
947     }
948
949     if(stencilBufferAvailable == Integration::StencilBufferAvailable::TRUE)
950     {
951       mImpl->currentContext->ClearStencil(0);
952       mImpl->currentContext->StencilMask(0xFF); // 8 bit stencil mask, all 1's
953       clearMask |= GL_STENCIL_BUFFER_BIT;
954     }
955
956     if(!instruction.mIgnoreRenderToFbo && (instruction.mFrameBuffer != nullptr))
957     {
958       // Offscreen buffer rendering
959       if(instruction.mIsViewportSet)
960       {
961         // For glViewport the lower-left corner is (0,0)
962         const int32_t y = (instruction.mFrameBuffer->GetHeight() - instruction.mViewport.height) - instruction.mViewport.y;
963         viewportRect.Set(instruction.mViewport.x, y, instruction.mViewport.width, instruction.mViewport.height);
964       }
965       else
966       {
967         viewportRect.Set(0, 0, instruction.mFrameBuffer->GetWidth(), instruction.mFrameBuffer->GetHeight());
968       }
969       surfaceOrientation = 0;
970     }
971     else // No Offscreen frame buffer rendering
972     {
973       // Check whether a viewport is specified, otherwise the full surface size is used
974       if(instruction.mIsViewportSet)
975       {
976         // For glViewport the lower-left corner is (0,0)
977         const int32_t y = (surfaceRect.height - instruction.mViewport.height) - instruction.mViewport.y;
978         viewportRect.Set(instruction.mViewport.x, y, instruction.mViewport.width, instruction.mViewport.height);
979       }
980       else
981       {
982         viewportRect = surfaceRect;
983       }
984     }
985
986     // Set surface orientation
987     mImpl->currentContext->SetSurfaceOrientation(surfaceOrientation);
988
989     /*** Clear region of framebuffer or surface before drawing ***/
990
991     bool clearFullFrameRect = true;
992     if(instruction.mFrameBuffer != nullptr)
993     {
994       Viewport frameRect(0, 0, instruction.mFrameBuffer->GetWidth(), instruction.mFrameBuffer->GetHeight());
995       clearFullFrameRect = (frameRect == viewportRect);
996     }
997     else
998     {
999       clearFullFrameRect = (surfaceRect == viewportRect);
1000     }
1001
1002     if(!clippingRect.IsEmpty())
1003     {
1004       if(!clippingRect.Intersect(viewportRect))
1005       {
1006         DALI_LOG_ERROR("Invalid clipping rect %d %d %d %d\n", clippingRect.x, clippingRect.y, clippingRect.width, clippingRect.height);
1007         clippingRect = Rect<int>();
1008       }
1009       clearFullFrameRect = false;
1010     }
1011
1012     // @todo The following block should be a command in it's own right.
1013     // Currently takes account of surface orientation in Context.
1014     // Or move entirely to RenderPass implementation
1015     mImpl->currentContext->Viewport(viewportRect.x, viewportRect.y, viewportRect.width, viewportRect.height);
1016     if(instruction.mIsClearColorSet)
1017     {
1018       mImpl->currentContext->ClearColor(clearColor.r,
1019                                         clearColor.g,
1020                                         clearColor.b,
1021                                         clearColor.a);
1022       if(!clearFullFrameRect)
1023       {
1024         if(!clippingRect.IsEmpty())
1025         {
1026           mImpl->currentContext->SetScissorTest(true);
1027           mImpl->currentContext->Scissor(clippingRect.x, clippingRect.y, clippingRect.width, clippingRect.height);
1028           mImpl->currentContext->Clear(clearMask, Context::FORCE_CLEAR);
1029           mImpl->currentContext->SetScissorTest(false);
1030         }
1031         else
1032         {
1033           mImpl->currentContext->SetScissorTest(true);
1034           mImpl->currentContext->Scissor(viewportRect.x, viewportRect.y, viewportRect.width, viewportRect.height);
1035           mImpl->currentContext->Clear(clearMask, Context::FORCE_CLEAR);
1036           mImpl->currentContext->SetScissorTest(false);
1037         }
1038       }
1039       else
1040       {
1041         mImpl->currentContext->SetScissorTest(false);
1042         mImpl->currentContext->Clear(clearMask, Context::FORCE_CLEAR);
1043       }
1044     }
1045
1046     // Clear the list of bound textures
1047     mImpl->boundTextures.Clear();
1048
1049     mImpl->renderAlgorithms.ProcessRenderInstruction(
1050       instruction,
1051       *mImpl->currentContext,
1052       mImpl->renderBufferIndex,
1053       depthBufferAvailable,
1054       stencilBufferAvailable,
1055       mImpl->boundTextures,
1056       viewportRect,
1057       clippingRect,
1058       surfaceOrientation);
1059
1060     // Synchronise the FBO/Texture access when there are multiple contexts
1061     if(mImpl->currentContext->IsSurfacelessContextSupported())
1062     {
1063       // Check whether any bound texture is in the dependency list
1064       bool textureFound = false;
1065
1066       if(mImpl->boundTextures.Count() > 0u && mImpl->textureDependencyList.Count() > 0u)
1067       {
1068         for(auto texture : mImpl->textureDependencyList)
1069         {
1070           textureFound = std::find_if(mImpl->boundTextures.Begin(), mImpl->boundTextures.End(), [texture](Graphics::Texture* graphicsTexture) {
1071                            return texture == graphicsTexture;
1072                          }) != mImpl->boundTextures.End();
1073         }
1074       }
1075
1076       if(textureFound)
1077       {
1078         if(instruction.mFrameBuffer)
1079         {
1080           // For off-screen buffer
1081
1082           // Wait until all rendering calls for the currently context are executed
1083           // mImpl->graphicsController.GetGlContextHelperAbstraction().WaitClient();
1084
1085           // Clear the dependency list
1086           mImpl->textureDependencyList.Clear();
1087         }
1088         else
1089         {
1090           // Worker thread lambda function
1091           auto& glContextHelperAbstraction = mImpl->graphicsController.GetGlContextHelperAbstraction();
1092           auto  workerFunction             = [&glContextHelperAbstraction](int workerThread) {
1093             // Switch to the shared context in the worker thread
1094             glContextHelperAbstraction.MakeSurfacelessContextCurrent();
1095
1096             // Wait until all rendering calls for the shared context are executed
1097             glContextHelperAbstraction.WaitClient();
1098
1099             // Must clear the context in the worker thread
1100             // Otherwise the shared context cannot be switched to from the render thread
1101             glContextHelperAbstraction.MakeContextNull();
1102           };
1103
1104           auto future = mImpl->threadPool->SubmitTask(0u, workerFunction);
1105           if(future)
1106           {
1107             mImpl->threadPool->Wait();
1108
1109             // Clear the dependency list
1110             mImpl->textureDependencyList.Clear();
1111           }
1112         }
1113       }
1114     }
1115
1116     if(instruction.mRenderTracker && instruction.mFrameBuffer)
1117     {
1118       // This will create a sync object every frame this render tracker
1119       // is alive (though it should be now be created only for
1120       // render-once render tasks)
1121       instruction.mRenderTracker->CreateSyncObject(mImpl->graphicsController.GetGlSyncAbstraction());
1122       instruction.mRenderTracker = nullptr; // Only create once.
1123     }
1124
1125     if(renderToFbo)
1126     {
1127       mImpl->currentContext->Flush();
1128     }
1129
1130     // End render pass
1131     mainCommandBuffer->EndRenderPass();
1132     mImpl->renderAlgorithms.SubmitCommandBuffer();
1133   }
1134
1135   GLenum attachments[] = {GL_DEPTH, GL_STENCIL};
1136   mImpl->currentContext->InvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments);
1137 }
1138
1139 void RenderManager::PostRender(bool uploadOnly)
1140 {
1141   // Submit main command buffer
1142   //mImpl->renderAlgorithms.SubmitCommandBuffer();
1143
1144   if(!uploadOnly)
1145   {
1146     if(mImpl->currentContext->IsSurfacelessContextSupported())
1147     {
1148       mImpl->graphicsController.GetGlContextHelperAbstraction().MakeSurfacelessContextCurrent();
1149     }
1150
1151     GLenum attachments[] = {GL_DEPTH, GL_STENCIL};
1152     mImpl->context.InvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments);
1153   }
1154
1155   //Notify RenderGeometries that rendering has finished
1156   for(auto&& iter : mImpl->geometryContainer)
1157   {
1158     iter->OnRenderFinished();
1159   }
1160
1161   mImpl->UpdateTrackers();
1162
1163   uint32_t count = 0u;
1164   for(uint32_t i = 0; i < mImpl->sceneContainer.size(); ++i)
1165   {
1166     count += mImpl->sceneContainer[i]->GetRenderInstructions().Count(mImpl->renderBufferIndex);
1167   }
1168
1169   const bool haveInstructions = count > 0u;
1170
1171   // If this frame was rendered due to instructions existing, we mark this so we know to clear the next frame.
1172   mImpl->lastFrameWasRendered = haveInstructions;
1173
1174   /**
1175    * The rendering has finished; swap to the next buffer.
1176    * Ideally the update has just finished using this buffer; otherwise the render thread
1177    * should block until the update has finished.
1178    */
1179   mImpl->renderBufferIndex = (0 != mImpl->renderBufferIndex) ? 0 : 1;
1180
1181   DALI_PRINT_RENDER_END();
1182 }
1183
1184 } // namespace SceneGraph
1185
1186 } // namespace Internal
1187
1188 } // namespace Dali