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