Removing GL usage from dali core
[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
28 #include <dali/internal/event/common/scene-impl.h>
29
30 #include <dali/internal/update/common/scene-graph-scene.h>
31 #include <dali/internal/update/render-tasks/scene-graph-camera.h>
32
33 #include <dali/internal/render/common/render-algorithms.h>
34 #include <dali/internal/render/common/render-debug.h>
35 #include <dali/internal/render/common/render-instruction.h>
36 #include <dali/internal/render/common/render-tracker.h>
37 #include <dali/internal/render/queue/render-queue.h>
38 #include <dali/internal/render/renderers/render-frame-buffer.h>
39 #include <dali/internal/render/renderers/render-texture.h>
40 #include <dali/internal/render/renderers/shader-cache.h>
41 #include <dali/internal/render/renderers/uniform-buffer-manager.h>
42 #include <dali/internal/render/renderers/uniform-buffer-view-pool.h>
43 #include <dali/internal/render/shaders/program-controller.h>
44
45 #include <dali/internal/render/renderers/uniform-buffer-manager.h>
46
47 namespace Dali
48 {
49 namespace Internal
50 {
51 namespace SceneGraph
52 {
53 #if defined(DEBUG_ENABLED)
54 namespace
55 {
56 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RENDER_MANAGER");
57 } // unnamed namespace
58 #endif
59
60 /**
61  * Structure to contain internal data
62  */
63 struct RenderManager::Impl
64 {
65   Impl(Graphics::Controller&               graphicsController,
66        Integration::DepthBufferAvailable   depthBufferAvailableParam,
67        Integration::StencilBufferAvailable stencilBufferAvailableParam,
68        Integration::PartialUpdateAvailable partialUpdateAvailableParam)
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
92   ~Impl()
93   {
94     threadPool.reset(nullptr); // reset now to maintain correct destruction order
95   }
96
97   void AddRenderTracker(Render::RenderTracker* renderTracker)
98   {
99     DALI_ASSERT_DEBUG(renderTracker != nullptr);
100     mRenderTrackers.PushBack(renderTracker);
101   }
102
103   void RemoveRenderTracker(Render::RenderTracker* renderTracker)
104   {
105     mRenderTrackers.EraseObject(renderTracker);
106   }
107
108   void UpdateTrackers()
109   {
110     for(auto&& iter : mRenderTrackers)
111     {
112       iter->PollSyncObject();
113     }
114   }
115
116   // the order is important for destruction,
117   Graphics::Controller& graphicsController;
118   RenderQueue           renderQueue; ///< A message queue for receiving messages from the update-thread.
119
120   std::vector<SceneGraph::Scene*> sceneContainer; ///< List of pointers to the scene graph objects of the scenes
121
122   Render::RenderAlgorithms renderAlgorithms; ///< The RenderAlgorithms object is used to action the renders required by a RenderInstruction
123
124   uint32_t    frameCount;        ///< The current frame count
125   BufferIndex renderBufferIndex; ///< The index of the buffer to read from; this is opposite of the "update" buffer
126
127   OwnerContainer<Render::Renderer*>     rendererContainer;     ///< List of owned renderers
128   OwnerContainer<Render::Sampler*>      samplerContainer;      ///< List of owned samplers
129   OwnerContainer<Render::Texture*>      textureContainer;      ///< List of owned textures
130   OwnerContainer<Render::FrameBuffer*>  frameBufferContainer;  ///< List of owned framebuffers
131   OwnerContainer<Render::VertexBuffer*> vertexBufferContainer; ///< List of owned vertex buffers
132   OwnerContainer<Render::Geometry*>     geometryContainer;     ///< List of owned Geometries
133
134   bool lastFrameWasRendered; ///< Keeps track of the last frame being rendered due to having render instructions
135
136   OwnerContainer<Render::RenderTracker*> mRenderTrackers; ///< List of render trackers
137
138   ProgramController   programController; ///< Owner of the programs
139   Render::ShaderCache shaderCache;       ///< The cache for the graphics shaders
140
141   std::unique_ptr<Render::UniformBufferManager> uniformBufferManager; ///< The uniform buffer manager
142
143   Integration::DepthBufferAvailable   depthBufferAvailable;   ///< Whether the depth buffer is available
144   Integration::StencilBufferAvailable stencilBufferAvailable; ///< Whether the stencil buffer is available
145   Integration::PartialUpdateAvailable partialUpdateAvailable; ///< Whether the partial update is available
146
147   std::unique_ptr<Dali::ThreadPool> threadPool;            ///< The thread pool
148   Vector<Graphics::Texture*>        boundTextures;         ///< The textures bound for rendering
149   Vector<Graphics::Texture*>        textureDependencyList; ///< The dependency list of bound textures
150 };
151
152 RenderManager* RenderManager::New(Graphics::Controller&               graphicsController,
153                                   Integration::DepthBufferAvailable   depthBufferAvailable,
154                                   Integration::StencilBufferAvailable stencilBufferAvailable,
155                                   Integration::PartialUpdateAvailable partialUpdateAvailable)
156 {
157   auto* manager  = new RenderManager;
158   manager->mImpl = new Impl(graphicsController,
159                             depthBufferAvailable,
160                             stencilBufferAvailable,
161                             partialUpdateAvailable);
162   return manager;
163 }
164
165 RenderManager::RenderManager()
166 : mImpl(nullptr)
167 {
168 }
169
170 RenderManager::~RenderManager()
171 {
172   delete mImpl;
173 }
174
175 RenderQueue& RenderManager::GetRenderQueue()
176 {
177   return mImpl->renderQueue;
178 }
179
180 void RenderManager::SetShaderSaver(ShaderSaver& upstream)
181 {
182 }
183
184 void RenderManager::AddRenderer(OwnerPointer<Render::Renderer>& renderer)
185 {
186   // Initialize the renderer as we are now in render thread
187   renderer->Initialize(mImpl->graphicsController, mImpl->programController, mImpl->shaderCache, *(mImpl->uniformBufferManager.get()));
188
189   mImpl->rendererContainer.PushBack(renderer.Release());
190 }
191
192 void RenderManager::RemoveRenderer(Render::Renderer* renderer)
193 {
194   mImpl->rendererContainer.EraseObject(renderer);
195 }
196
197 void RenderManager::AddSampler(OwnerPointer<Render::Sampler>& sampler)
198 {
199   sampler->Initialize(mImpl->graphicsController);
200   mImpl->samplerContainer.PushBack(sampler.Release());
201 }
202
203 void RenderManager::RemoveSampler(Render::Sampler* sampler)
204 {
205   mImpl->samplerContainer.EraseObject(sampler);
206 }
207
208 void RenderManager::AddTexture(OwnerPointer<Render::Texture>& texture)
209 {
210   texture->Initialize(mImpl->graphicsController);
211   mImpl->textureContainer.PushBack(texture.Release());
212 }
213
214 void RenderManager::RemoveTexture(Render::Texture* texture)
215 {
216   DALI_ASSERT_DEBUG(NULL != texture);
217
218   // Find the texture, use reference to pointer so we can do the erase safely
219   for(auto&& iter : mImpl->textureContainer)
220   {
221     if(iter == texture)
222     {
223       texture->Destroy();
224       mImpl->textureContainer.Erase(&iter); // Texture found; now destroy it
225       return;
226     }
227   }
228 }
229
230 void RenderManager::UploadTexture(Render::Texture* texture, PixelDataPtr pixelData, const Texture::UploadParams& params)
231 {
232   texture->Upload(pixelData, params);
233 }
234
235 void RenderManager::GenerateMipmaps(Render::Texture* texture)
236 {
237   texture->GenerateMipmaps();
238 }
239
240 void RenderManager::SetFilterMode(Render::Sampler* sampler, uint32_t minFilterMode, uint32_t magFilterMode)
241 {
242   sampler->SetFilterMode(static_cast<Dali::FilterMode::Type>(minFilterMode),
243                          static_cast<Dali::FilterMode::Type>(magFilterMode));
244 }
245
246 void RenderManager::SetWrapMode(Render::Sampler* sampler, uint32_t rWrapMode, uint32_t sWrapMode, uint32_t tWrapMode)
247 {
248   sampler->SetWrapMode(static_cast<Dali::WrapMode::Type>(rWrapMode),
249                        static_cast<Dali::WrapMode::Type>(sWrapMode),
250                        static_cast<Dali::WrapMode::Type>(tWrapMode));
251 }
252
253 void RenderManager::AddFrameBuffer(OwnerPointer<Render::FrameBuffer>& frameBuffer)
254 {
255   Render::FrameBuffer* frameBufferPtr = frameBuffer.Release();
256   mImpl->frameBufferContainer.PushBack(frameBufferPtr);
257   frameBufferPtr->Initialize(mImpl->graphicsController);
258 }
259
260 void RenderManager::RemoveFrameBuffer(Render::FrameBuffer* frameBuffer)
261 {
262   DALI_ASSERT_DEBUG(nullptr != frameBuffer);
263
264   // Find the sampler, use reference so we can safely do the erase
265   for(auto&& iter : mImpl->frameBufferContainer)
266   {
267     if(iter == frameBuffer)
268     {
269       frameBuffer->Destroy();
270       mImpl->frameBufferContainer.Erase(&iter); // frameBuffer found; now destroy it
271
272       break;
273     }
274   }
275 }
276
277 void RenderManager::InitializeScene(SceneGraph::Scene* scene)
278 {
279   scene->Initialize(mImpl->graphicsController, mImpl->depthBufferAvailable, mImpl->stencilBufferAvailable);
280   mImpl->sceneContainer.push_back(scene);
281 }
282
283 void RenderManager::UninitializeScene(SceneGraph::Scene* scene)
284 {
285   auto iter = std::find(mImpl->sceneContainer.begin(), mImpl->sceneContainer.end(), scene);
286   if(iter != mImpl->sceneContainer.end())
287   {
288     mImpl->sceneContainer.erase(iter);
289   }
290 }
291
292 void RenderManager::SurfaceReplaced(SceneGraph::Scene* scene)
293 {
294   scene->Initialize(mImpl->graphicsController, mImpl->depthBufferAvailable, mImpl->stencilBufferAvailable);
295 }
296
297 void RenderManager::AttachColorTextureToFrameBuffer(Render::FrameBuffer* frameBuffer, Render::Texture* texture, uint32_t mipmapLevel, uint32_t layer)
298 {
299   frameBuffer->AttachColorTexture(texture, mipmapLevel, layer);
300 }
301
302 void RenderManager::AttachDepthTextureToFrameBuffer(Render::FrameBuffer* frameBuffer, Render::Texture* texture, uint32_t mipmapLevel)
303 {
304   frameBuffer->AttachDepthTexture(texture, mipmapLevel);
305 }
306
307 void RenderManager::AttachDepthStencilTextureToFrameBuffer(Render::FrameBuffer* frameBuffer, Render::Texture* texture, uint32_t mipmapLevel)
308 {
309   frameBuffer->AttachDepthStencilTexture(texture, mipmapLevel);
310 }
311
312 void RenderManager::AddVertexBuffer(OwnerPointer<Render::VertexBuffer>& vertexBuffer)
313 {
314   mImpl->vertexBufferContainer.PushBack(vertexBuffer.Release());
315 }
316
317 void RenderManager::RemoveVertexBuffer(Render::VertexBuffer* vertexBuffer)
318 {
319   mImpl->vertexBufferContainer.EraseObject(vertexBuffer);
320 }
321
322 void RenderManager::SetVertexBufferFormat(Render::VertexBuffer* vertexBuffer, OwnerPointer<Render::VertexBuffer::Format>& format)
323 {
324   vertexBuffer->SetFormat(format.Release());
325 }
326
327 void RenderManager::SetVertexBufferData(Render::VertexBuffer* vertexBuffer, OwnerPointer<Vector<uint8_t>>& data, uint32_t size)
328 {
329   vertexBuffer->SetData(data.Release(), size);
330 }
331
332 void RenderManager::SetIndexBuffer(Render::Geometry* geometry, Dali::Vector<uint16_t>& indices)
333 {
334   geometry->SetIndexBuffer(indices);
335 }
336
337 void RenderManager::AddGeometry(OwnerPointer<Render::Geometry>& geometry)
338 {
339   mImpl->geometryContainer.PushBack(geometry.Release());
340 }
341
342 void RenderManager::RemoveGeometry(Render::Geometry* geometry)
343 {
344   mImpl->geometryContainer.EraseObject(geometry);
345 }
346
347 void RenderManager::AttachVertexBuffer(Render::Geometry* geometry, Render::VertexBuffer* vertexBuffer)
348 {
349   DALI_ASSERT_DEBUG(nullptr != geometry);
350
351   // Find the geometry
352   for(auto&& iter : mImpl->geometryContainer)
353   {
354     if(iter == geometry)
355     {
356       iter->AddVertexBuffer(vertexBuffer);
357       break;
358     }
359   }
360 }
361
362 void RenderManager::RemoveVertexBuffer(Render::Geometry* geometry, Render::VertexBuffer* vertexBuffer)
363 {
364   DALI_ASSERT_DEBUG(nullptr != geometry);
365
366   // Find the geometry
367   for(auto&& iter : mImpl->geometryContainer)
368   {
369     if(iter == geometry)
370     {
371       iter->RemoveVertexBuffer(vertexBuffer);
372       break;
373     }
374   }
375 }
376
377 void RenderManager::SetGeometryType(Render::Geometry* geometry, uint32_t geometryType)
378 {
379   geometry->SetType(Render::Geometry::Type(geometryType));
380 }
381
382 void RenderManager::AddRenderTracker(Render::RenderTracker* renderTracker)
383 {
384   mImpl->AddRenderTracker(renderTracker);
385 }
386
387 void RenderManager::RemoveRenderTracker(Render::RenderTracker* renderTracker)
388 {
389   mImpl->RemoveRenderTracker(renderTracker);
390 }
391
392 void RenderManager::PreRender(Integration::RenderStatus& status, bool forceClear, bool uploadOnly)
393 {
394   DALI_PRINT_RENDER_START(mImpl->renderBufferIndex);
395
396   // Rollback
397   mImpl->uniformBufferManager->GetUniformBufferViewPool(mImpl->renderBufferIndex)->Rollback();
398
399   // Increment the frame count at the beginning of each frame
400   ++mImpl->frameCount;
401
402   // Process messages queued during previous update
403   mImpl->renderQueue.ProcessMessages(mImpl->renderBufferIndex);
404
405   uint32_t count = 0u;
406   for(auto& i : mImpl->sceneContainer)
407   {
408     count += i->GetRenderInstructions().Count(mImpl->renderBufferIndex);
409   }
410
411   const bool haveInstructions = count > 0u;
412
413   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");
414
415   // Only render if we have instructions to render, or the last frame was rendered (and therefore a clear is required).
416   if(haveInstructions || mImpl->lastFrameWasRendered || forceClear)
417   {
418     DALI_LOG_INFO(gLogFilter, Debug::General, "Render: Processing\n");
419
420     // Upload the geometries
421     for(auto& i : mImpl->sceneContainer)
422     {
423       RenderInstructionContainer& instructions = i->GetRenderInstructions();
424       for(uint32_t j = 0; j < instructions.Count(mImpl->renderBufferIndex); ++j)
425       {
426         RenderInstruction& instruction = instructions.At(mImpl->renderBufferIndex, j);
427
428         const Matrix* viewMatrix       = instruction.GetViewMatrix(mImpl->renderBufferIndex);
429         const Matrix* projectionMatrix = instruction.GetProjectionMatrix(mImpl->renderBufferIndex);
430
431         DALI_ASSERT_DEBUG(viewMatrix);
432         DALI_ASSERT_DEBUG(projectionMatrix);
433
434         if(viewMatrix && projectionMatrix)
435         {
436           const RenderListContainer::SizeType renderListCount = instruction.RenderListCount();
437
438           // Iterate through each render list.
439           for(RenderListContainer::SizeType index = 0; index < renderListCount; ++index)
440           {
441             const RenderList* renderList = instruction.GetRenderList(index);
442
443             if(renderList && !renderList->IsEmpty())
444             {
445               const std::size_t itemCount = renderList->Count();
446               for(uint32_t itemIndex = 0u; itemIndex < itemCount; ++itemIndex)
447               {
448                 const RenderItem& item = renderList->GetItem(itemIndex);
449                 if(DALI_LIKELY(item.mRenderer))
450                 {
451                   item.mRenderer->Upload();
452                 }
453               }
454             }
455           }
456         }
457       }
458     }
459   }
460 }
461
462 void RenderManager::PreRender(Integration::Scene& scene, std::vector<Rect<int>>& damagedRects)
463 {
464   if(mImpl->partialUpdateAvailable != Integration::PartialUpdateAvailable::TRUE)
465   {
466     return;
467   }
468
469   Internal::Scene&   sceneInternal = GetImplementation(scene);
470   SceneGraph::Scene* sceneObject   = sceneInternal.GetSceneObject();
471
472   if(sceneObject->IsRenderingSkipped())
473   {
474     // We don't need to calculate dirty rects
475     return;
476   }
477
478   class DamagedRectsCleaner
479   {
480   public:
481     explicit DamagedRectsCleaner(std::vector<Rect<int>>& damagedRects)
482     : mDamagedRects(damagedRects),
483       mCleanOnReturn(true)
484     {
485     }
486
487     void SetCleanOnReturn(bool cleanOnReturn)
488     {
489       mCleanOnReturn = cleanOnReturn;
490     }
491
492     ~DamagedRectsCleaner()
493     {
494       if(mCleanOnReturn)
495       {
496         mDamagedRects.clear();
497       }
498     }
499
500   private:
501     std::vector<Rect<int>>& mDamagedRects;
502     bool                    mCleanOnReturn;
503   };
504
505   Rect<int32_t> surfaceRect = sceneObject->GetSurfaceRect();
506
507   // Clean collected dirty/damaged rects on exit if 3d layer or 3d node or other conditions.
508   DamagedRectsCleaner damagedRectCleaner(damagedRects);
509
510   // Mark previous dirty rects in the sorted array. The array is already sorted by node and renderer, frame number.
511   // so you don't need to sort: std::stable_sort(itemsDirtyRects.begin(), itemsDirtyRects.end());
512   std::vector<DirtyRect>& itemsDirtyRects = sceneInternal.GetItemsDirtyRects();
513   for(DirtyRect& dirtyRect : itemsDirtyRects)
514   {
515     dirtyRect.visited = false;
516   }
517
518   uint32_t instructionCount = sceneObject->GetRenderInstructions().Count(mImpl->renderBufferIndex);
519   for(uint32_t i = 0; i < instructionCount; ++i)
520   {
521     RenderInstruction& instruction = sceneObject->GetRenderInstructions().At(mImpl->renderBufferIndex, i);
522
523     if(instruction.mFrameBuffer)
524     {
525       return; // TODO: reset, we don't deal with render tasks with framebuffers (for now)
526     }
527
528     const Camera* camera = instruction.GetCamera();
529     if(camera->mType == Camera::DEFAULT_TYPE && camera->mTargetPosition == Camera::DEFAULT_TARGET_POSITION)
530     {
531       const Node* node = instruction.GetCamera()->GetNode();
532       if(node)
533       {
534         Vector3    position;
535         Vector3    scale;
536         Quaternion orientation;
537         node->GetWorldMatrix(mImpl->renderBufferIndex).GetTransformComponents(position, orientation, scale);
538
539         Vector3 orientationAxis;
540         Radian  orientationAngle;
541         orientation.ToAxisAngle(orientationAxis, orientationAngle);
542
543         if(position.x > Math::MACHINE_EPSILON_10000 ||
544            position.y > Math::MACHINE_EPSILON_10000 ||
545            orientationAxis != Vector3(0.0f, 1.0f, 0.0f) ||
546            orientationAngle != ANGLE_180 ||
547            scale != Vector3(1.0f, 1.0f, 1.0f))
548         {
549           return;
550         }
551       }
552     }
553     else
554     {
555       return;
556     }
557
558     Rect<int32_t> viewportRect;
559     if(instruction.mIsViewportSet)
560     {
561       const int32_t y = (surfaceRect.height - instruction.mViewport.height) - instruction.mViewport.y;
562       viewportRect.Set(instruction.mViewport.x, y, instruction.mViewport.width, instruction.mViewport.height);
563       if(viewportRect.IsEmpty() || !viewportRect.IsValid())
564       {
565         return; // just skip funny use cases for now, empty viewport means it is set somewhere else
566       }
567     }
568     else
569     {
570       viewportRect = surfaceRect;
571     }
572
573     const Matrix* viewMatrix       = instruction.GetViewMatrix(mImpl->renderBufferIndex);
574     const Matrix* projectionMatrix = instruction.GetProjectionMatrix(mImpl->renderBufferIndex);
575     if(viewMatrix && projectionMatrix)
576     {
577       const RenderListContainer::SizeType count = instruction.RenderListCount();
578       for(RenderListContainer::SizeType index = 0u; index < count; ++index)
579       {
580         const RenderList* renderList = instruction.GetRenderList(index);
581         if(renderList && !renderList->IsEmpty())
582         {
583           const std::size_t listCount = renderList->Count();
584           for(uint32_t listIndex = 0u; listIndex < listCount; ++listIndex)
585           {
586             RenderItem& item = renderList->GetItem(listIndex);
587             // If the item does 3D transformation, do early exit and clean the damaged rect array
588             if(item.mUpdateSize == Vector3::ZERO)
589             {
590               return;
591             }
592
593             Rect<int> rect;
594             DirtyRect dirtyRect(item.mNode, item.mRenderer, mImpl->frameCount, rect);
595             // If the item refers to updated node or renderer.
596             if(item.mIsUpdated ||
597                (item.mNode &&
598                 (item.mNode->Updated() || (item.mRenderer && item.mRenderer->Updated(mImpl->renderBufferIndex, item.mNode)))))
599             {
600               item.mIsUpdated = false;
601               item.mNode->SetUpdated(false);
602
603               rect = item.CalculateViewportSpaceAABB(item.mUpdateSize, viewportRect.width, viewportRect.height);
604               if(rect.IsValid() && rect.Intersect(viewportRect) && !rect.IsEmpty())
605               {
606                 const int left   = rect.x;
607                 const int top    = rect.y;
608                 const int right  = rect.x + rect.width;
609                 const int bottom = rect.y + rect.height;
610                 rect.x           = (left / 16) * 16;
611                 rect.y           = (top / 16) * 16;
612                 rect.width       = ((right + 16) / 16) * 16 - rect.x;
613                 rect.height      = ((bottom + 16) / 16) * 16 - rect.y;
614
615                 // Found valid dirty rect.
616                 // 1. Insert it in the sorted array of the dirty rects.
617                 // 2. Mark the related dirty rects as visited so they will not be removed below.
618                 // 3. Keep only last 3 dirty rects for the same node and renderer (Tizen uses 3 back buffers, Ubuntu 1).
619                 dirtyRect.rect    = rect;
620                 auto dirtyRectPos = std::lower_bound(itemsDirtyRects.begin(), itemsDirtyRects.end(), dirtyRect);
621                 dirtyRectPos      = itemsDirtyRects.insert(dirtyRectPos, dirtyRect);
622
623                 int c = 1;
624                 while(++dirtyRectPos != itemsDirtyRects.end())
625                 {
626                   if(dirtyRectPos->node != item.mNode || dirtyRectPos->renderer != item.mRenderer)
627                   {
628                     break;
629                   }
630
631                   dirtyRectPos->visited = true;
632                   Rect<int>& dirtRect   = dirtyRectPos->rect;
633                   rect.Merge(dirtRect);
634
635                   c++;
636                   if(c > 3) // no more then 3 previous rects
637                   {
638                     itemsDirtyRects.erase(dirtyRectPos);
639                     break;
640                   }
641                 }
642
643                 damagedRects.push_back(rect);
644               }
645             }
646             else
647             {
648               // 1. The item is not dirty, the node and renderer referenced by the item are still exist.
649               // 2. Mark the related dirty rects as visited so they will not be removed below.
650               auto dirtyRectPos = std::lower_bound(itemsDirtyRects.begin(), itemsDirtyRects.end(), dirtyRect);
651               while(dirtyRectPos != itemsDirtyRects.end())
652               {
653                 if(dirtyRectPos->node != item.mNode || dirtyRectPos->renderer != item.mRenderer)
654                 {
655                   break;
656                 }
657
658                 dirtyRectPos->visited = true;
659                 dirtyRectPos++;
660               }
661             }
662           }
663         }
664       }
665     }
666   }
667
668   // Check removed nodes or removed renderers dirty rects
669   auto i = itemsDirtyRects.begin();
670   auto j = itemsDirtyRects.begin();
671   while(i != itemsDirtyRects.end())
672   {
673     if(i->visited)
674     {
675       *j++ = *i;
676     }
677     else
678     {
679       Rect<int>& dirtRect = i->rect;
680       damagedRects.push_back(dirtRect);
681     }
682     i++;
683   }
684
685   itemsDirtyRects.resize(j - itemsDirtyRects.begin());
686   damagedRectCleaner.SetCleanOnReturn(false);
687 }
688
689 void RenderManager::RenderScene(Integration::RenderStatus& status, Integration::Scene& scene, bool renderToFbo)
690 {
691   Rect<int> clippingRect;
692   RenderScene(status, scene, renderToFbo, clippingRect);
693 }
694
695 void RenderManager::RenderScene(Integration::RenderStatus& status, Integration::Scene& scene, bool renderToFbo, Rect<int>& clippingRect)
696 {
697   // Reset main algorithms command buffer
698   mImpl->renderAlgorithms.ResetCommandBuffer();
699
700   auto mainCommandBuffer = mImpl->renderAlgorithms.GetMainCommandBuffer();
701
702   Internal::Scene&   sceneInternal = GetImplementation(scene);
703   SceneGraph::Scene* sceneObject   = sceneInternal.GetSceneObject();
704
705   uint32_t count = sceneObject->GetRenderInstructions().Count(mImpl->renderBufferIndex);
706
707   std::vector<Graphics::RenderTarget*> targetstoPresent;
708
709   for(uint32_t i = 0; i < count; ++i)
710   {
711     RenderInstruction& instruction = sceneObject->GetRenderInstructions().At(mImpl->renderBufferIndex, i);
712
713     if((renderToFbo && !instruction.mFrameBuffer) || (!renderToFbo && instruction.mFrameBuffer))
714     {
715       continue; // skip
716     }
717
718     // Mark that we will require a post-render step to be performed (includes swap-buffers).
719     status.SetNeedsPostRender(true);
720
721     Rect<int32_t> viewportRect;
722
723     Rect<int32_t> surfaceRect        = sceneObject->GetSurfaceRect();
724     int32_t       surfaceOrientation = sceneObject->GetSurfaceOrientation();
725
726     // @todo Should these be part of scene?
727     Integration::DepthBufferAvailable   depthBufferAvailable   = mImpl->depthBufferAvailable;
728     Integration::StencilBufferAvailable stencilBufferAvailable = mImpl->stencilBufferAvailable;
729
730     Graphics::RenderTarget*           currentRenderTarget = nullptr;
731     Graphics::RenderPass*             currentRenderPass   = nullptr;
732     std::vector<Graphics::ClearValue> currentClearValues{};
733
734     if(instruction.mFrameBuffer)
735     {
736       // Ensure graphics framebuffer is created, bind attachments and create render passes
737       // Only happens once per framebuffer. If the create fails, e.g. no attachments yet,
738       // then don't render to this framebuffer.
739       if(!instruction.mFrameBuffer->GetGraphicsObject())
740       {
741         const bool created = instruction.mFrameBuffer->CreateGraphicsObjects();
742         if(!created)
743         {
744           continue;
745         }
746       }
747
748       auto& clearValues = instruction.mFrameBuffer->GetGraphicsRenderPassClearValues();
749
750       // Set the clear color for first color attachment
751       if(instruction.mIsClearColorSet && !clearValues.empty())
752       {
753         clearValues[0].color = {
754           instruction.mClearColor.r,
755           instruction.mClearColor.g,
756           instruction.mClearColor.b,
757           instruction.mClearColor.a};
758       }
759
760       currentClearValues = clearValues;
761
762       auto loadOp = instruction.mIsClearColorSet ? Graphics::AttachmentLoadOp::CLEAR : Graphics::AttachmentLoadOp::LOAD;
763
764       // offscreen buffer
765       currentRenderTarget = instruction.mFrameBuffer->GetGraphicsRenderTarget();
766       currentRenderPass   = instruction.mFrameBuffer->GetGraphicsRenderPass(loadOp, Graphics::AttachmentStoreOp::STORE);
767     }
768     else // no framebuffer
769     {
770       // surface
771       auto& clearValues = sceneObject->GetGraphicsRenderPassClearValues();
772
773       if(instruction.mIsClearColorSet)
774       {
775         clearValues[0].color = {
776           instruction.mClearColor.r,
777           instruction.mClearColor.g,
778           instruction.mClearColor.b,
779           instruction.mClearColor.a};
780       }
781
782       currentClearValues = clearValues;
783
784       // @todo SceneObject should already have the depth clear / stencil clear in the clearValues array.
785       // if the window has a depth/stencil buffer.
786       if((depthBufferAvailable == Integration::DepthBufferAvailable::TRUE ||
787           stencilBufferAvailable == Integration::StencilBufferAvailable::TRUE) &&
788          (currentClearValues.size() <= 1))
789       {
790         currentClearValues.emplace_back();
791         currentClearValues.back().depthStencil.depth   = 0;
792         currentClearValues.back().depthStencil.stencil = 0;
793       }
794
795       auto loadOp = instruction.mIsClearColorSet ? Graphics::AttachmentLoadOp::CLEAR : Graphics::AttachmentLoadOp::LOAD;
796
797       currentRenderTarget = sceneObject->GetSurfaceRenderTarget();
798       currentRenderPass   = sceneObject->GetGraphicsRenderPass(loadOp, Graphics::AttachmentStoreOp::STORE);
799     }
800
801     targetstoPresent.emplace_back(currentRenderTarget);
802
803     // reset the program matrices for all programs once per frame
804     // this ensures we will set view and projection matrix once per program per camera
805     mImpl->programController.ResetProgramMatrices();
806
807     if(instruction.mFrameBuffer)
808     {
809       // For each offscreen buffer, update the dependency list with the new texture id used by this frame buffer.
810       for(unsigned int i0 = 0, i1 = instruction.mFrameBuffer->GetColorAttachmentCount(); i0 < i1; ++i0)
811       {
812         mImpl->textureDependencyList.PushBack(instruction.mFrameBuffer->GetTexture(i0));
813       }
814     }
815
816     if(!instruction.mIgnoreRenderToFbo && (instruction.mFrameBuffer != nullptr))
817     {
818       // Offscreen buffer rendering
819       if(instruction.mIsViewportSet)
820       {
821         // For Viewport the lower-left corner is (0,0)
822         const int32_t y = (instruction.mFrameBuffer->GetHeight() - instruction.mViewport.height) - instruction.mViewport.y;
823         viewportRect.Set(instruction.mViewport.x, y, instruction.mViewport.width, instruction.mViewport.height);
824       }
825       else
826       {
827         viewportRect.Set(0, 0, instruction.mFrameBuffer->GetWidth(), instruction.mFrameBuffer->GetHeight());
828       }
829       surfaceOrientation = 0;
830     }
831     else // No Offscreen frame buffer rendering
832     {
833       // Check whether a viewport is specified, otherwise the full surface size is used
834       if(instruction.mIsViewportSet)
835       {
836         // For Viewport the lower-left corner is (0,0)
837         const int32_t y = (surfaceRect.height - instruction.mViewport.height) - instruction.mViewport.y;
838         viewportRect.Set(instruction.mViewport.x, y, instruction.mViewport.width, instruction.mViewport.height);
839       }
840       else
841       {
842         viewportRect = surfaceRect;
843       }
844     }
845
846     // Set surface orientation
847     // @todo Inform graphics impl by another route.
848     // was: mImpl->currentContext->SetSurfaceOrientation(surfaceOrientation);
849
850     /*** Clear region of framebuffer or surface before drawing ***/
851     bool clearFullFrameRect = (surfaceRect == viewportRect);
852     if(instruction.mFrameBuffer != nullptr)
853     {
854       Viewport frameRect(0, 0, instruction.mFrameBuffer->GetWidth(), instruction.mFrameBuffer->GetHeight());
855       clearFullFrameRect = (frameRect == viewportRect);
856     }
857
858     if(!clippingRect.IsEmpty())
859     {
860       if(!clippingRect.Intersect(viewportRect))
861       {
862         DALI_LOG_ERROR("Invalid clipping rect %d %d %d %d\n", clippingRect.x, clippingRect.y, clippingRect.width, clippingRect.height);
863         clippingRect = Rect<int>();
864       }
865       clearFullFrameRect = false;
866     }
867
868     Graphics::Rect2D scissorArea{viewportRect.x, viewportRect.y, uint32_t(viewportRect.width), uint32_t(viewportRect.height)};
869     if(instruction.mIsClearColorSet)
870     {
871       if(!clearFullFrameRect)
872       {
873         if(!clippingRect.IsEmpty())
874         {
875           scissorArea = {clippingRect.x, clippingRect.y, uint32_t(clippingRect.width), uint32_t(clippingRect.height)};
876         }
877       }
878     }
879
880     // Begin render pass
881     mainCommandBuffer->BeginRenderPass(
882       currentRenderPass,
883       currentRenderTarget,
884       scissorArea,
885       currentClearValues);
886
887     mainCommandBuffer->SetViewport({float(viewportRect.x),
888                                     float(viewportRect.y),
889                                     float(viewportRect.width),
890                                     float(viewportRect.height)});
891
892     // Clear the list of bound textures
893     mImpl->boundTextures.Clear();
894
895     mImpl->renderAlgorithms.ProcessRenderInstruction(
896       instruction,
897       mImpl->renderBufferIndex,
898       depthBufferAvailable,
899       stencilBufferAvailable,
900       mImpl->boundTextures,
901       viewportRect,
902       clippingRect,
903       surfaceOrientation);
904
905     Graphics::SyncObject* syncObject{nullptr};
906     // If the render instruction has an associated render tracker (owned separately)
907     // and framebuffer, create a one shot sync object, and use it to determine when
908     // the render pass has finished executing on GPU.
909     if(instruction.mRenderTracker && instruction.mFrameBuffer)
910     {
911       syncObject                 = instruction.mRenderTracker->CreateSyncObject(mImpl->graphicsController);
912       instruction.mRenderTracker = nullptr;
913     }
914     mainCommandBuffer->EndRenderPass(syncObject);
915   }
916   mImpl->renderAlgorithms.SubmitCommandBuffer();
917
918   std::sort(targetstoPresent.begin(), targetstoPresent.end());
919
920   Graphics::RenderTarget* rt = nullptr;
921   for(auto& target : targetstoPresent)
922   {
923     if(target != rt)
924     {
925       mImpl->graphicsController.PresentRenderTarget(target);
926       rt = target;
927     }
928   }
929 }
930
931 void RenderManager::PostRender(bool uploadOnly)
932 {
933   // Notify RenderGeometries that rendering has finished
934   for(auto&& iter : mImpl->geometryContainer)
935   {
936     iter->OnRenderFinished();
937   }
938
939   mImpl->UpdateTrackers();
940
941   uint32_t count = 0u;
942   for(auto& scene : mImpl->sceneContainer)
943   {
944     count += scene->GetRenderInstructions().Count(mImpl->renderBufferIndex);
945   }
946
947   const bool haveInstructions = count > 0u;
948
949   // If this frame was rendered due to instructions existing, we mark this so we know to clear the next frame.
950   mImpl->lastFrameWasRendered = haveInstructions;
951
952   /**
953    * The rendering has finished; swap to the next buffer.
954    * Ideally the update has just finished using this buffer; otherwise the render thread
955    * should block until the update has finished.
956    */
957   mImpl->renderBufferIndex = (0 != mImpl->renderBufferIndex) ? 0 : 1;
958
959   DALI_PRINT_RENDER_END();
960 }
961
962 } // namespace SceneGraph
963
964 } // namespace Internal
965
966 } // namespace Dali