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