[Tizen] Using shader list for precompile
[platform/core/uifw/dali-adaptor.git] / dali / internal / adaptor / common / combined-update-render-controller.cpp
1 /*
2  * Copyright (c) 2023 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/adaptor/common/combined-update-render-controller.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali/integration-api/platform-abstraction.h>
23 #include <dali/integration-api/shader-precompiler.h>
24 #include <errno.h>
25 #include <unistd.h>
26 #include "dali/public-api/common/dali-common.h"
27
28 // INTERNAL INCLUDES
29 #include <dali/integration-api/adaptor-framework/trigger-event-factory.h>
30 #include <dali/internal/adaptor/common/adaptor-internal-services.h>
31 #include <dali/internal/adaptor/common/combined-update-render-controller-debug.h>
32 #include <dali/internal/graphics/common/graphics-interface.h>
33 #include <dali/internal/graphics/gles/egl-graphics.h>
34 #include <dali/internal/system/common/environment-options.h>
35 #include <dali/internal/system/common/texture-upload-manager-impl.h>
36 #include <dali/internal/system/common/time-service.h>
37 #include <dali/internal/thread/common/thread-settings-impl.h>
38 #include <dali/internal/window-system/common/window-impl.h>
39
40 namespace Dali
41 {
42 namespace Internal
43 {
44 namespace Adaptor
45 {
46 namespace
47 {
48
49 const unsigned int CREATED_THREAD_COUNT = 1u;
50
51 const int CONTINUOUS = -1;
52 const int ONCE       = 1;
53
54 const unsigned int TRUE  = 1u;
55 const unsigned int FALSE = 0u;
56
57 const unsigned int MILLISECONDS_PER_SECOND(1e+3);
58 const float        NANOSECONDS_TO_SECOND(1e-9f);
59 const unsigned int NANOSECONDS_PER_SECOND(1e+9);
60 const unsigned int NANOSECONDS_PER_MILLISECOND(1e+6);
61
62 // The following values will get calculated at compile time
63 const float    DEFAULT_FRAME_DURATION_IN_SECONDS(1.0f / 60.0f);
64 const uint64_t DEFAULT_FRAME_DURATION_IN_MILLISECONDS(DEFAULT_FRAME_DURATION_IN_SECONDS* MILLISECONDS_PER_SECOND);
65 const uint64_t DEFAULT_FRAME_DURATION_IN_NANOSECONDS(DEFAULT_FRAME_DURATION_IN_SECONDS* NANOSECONDS_PER_SECOND);
66
67 /**
68  * Handles the use case when an update-request is received JUST before we process a sleep-request. If we did not have an update-request count then
69  * there is a danger that, on the event-thread we could have:
70  *  1) An update-request where we do nothing as Update/Render thread still running.
71  *  2) Quickly followed by a sleep-request being handled where we pause the Update/Render Thread (even though we have an update to process).
72  *
73  * Using a counter means we increment the counter on an update-request, and decrement it on a sleep-request. This handles the above scenario because:
74  *  1) MAIN THREAD:           Update Request: COUNTER = 1
75  *  2) UPDATE/RENDER THREAD:  Do Update/Render, then no Updates required -> Sleep Trigger
76  *  3) MAIN THREAD:           Update Request: COUNTER = 2
77  *  4) MAIN THREAD:           Sleep Request:  COUNTER = 1 -> We do not sleep just yet
78  *
79  * Also ensures we preserve battery life by only doing ONE update when the above use case is not triggered.
80  *  1) MAIN THREAD:           Update Request: COUNTER = 1
81  *  2) UPDATE/RENDER THREAD:  Do Update/Render, then no Updates required -> Sleep Trigger
82  *  3) MAIN THREAD:           Sleep Request:  COUNTER = 0 -> Go to sleep
83  */
84 const unsigned int MAXIMUM_UPDATE_REQUESTS = 2;
85 } // unnamed namespace
86
87 ///////////////////////////////////////////////////////////////////////////////////////////////////
88 // EVENT THREAD
89 ///////////////////////////////////////////////////////////////////////////////////////////////////
90
91 CombinedUpdateRenderController::CombinedUpdateRenderController(AdaptorInternalServices& adaptorInterfaces, const EnvironmentOptions& environmentOptions, ThreadMode threadMode)
92 : mFpsTracker(environmentOptions),
93   mUpdateStatusLogger(environmentOptions),
94   mEventThreadSemaphore(0),
95   mSurfaceSemaphore(0),
96   mUpdateRenderThreadWaitCondition(),
97   mAdaptorInterfaces(adaptorInterfaces),
98   mPerformanceInterface(adaptorInterfaces.GetPerformanceInterface()),
99   mCore(adaptorInterfaces.GetCore()),
100   mEnvironmentOptions(environmentOptions),
101   mNotificationTrigger(adaptorInterfaces.GetProcessCoreEventsTrigger()),
102   mSleepTrigger(NULL),
103   mPreRenderCallback(NULL),
104   mTextureUploadManager(adaptorInterfaces.GetTextureUploadManager()),
105   mUpdateRenderThread(NULL),
106   mDefaultFrameDelta(0.0f),
107   mDefaultFrameDurationMilliseconds(0u),
108   mDefaultFrameDurationNanoseconds(0u),
109   mDefaultHalfFrameNanoseconds(0u),
110   mUpdateRequestCount(0u),
111   mRunning(FALSE),
112   mThreadId(0),
113   mThreadMode(threadMode),
114   mUpdateRenderRunCount(0),
115   mDestroyUpdateRenderThread(FALSE),
116   mUpdateRenderThreadCanSleep(FALSE),
117   mPendingRequestUpdate(FALSE),
118   mUseElapsedTimeAfterWait(FALSE),
119   mNewSurface(NULL),
120   mDeletedSurface(nullptr),
121   mPostRendering(FALSE),
122   mSurfaceResized(0),
123   mForceClear(FALSE),
124   mUploadWithoutRendering(FALSE),
125   mFirstFrameAfterResume(FALSE)
126 {
127   LOG_EVENT_TRACE;
128
129   // Initialise frame delta/duration variables first
130   SetRenderRefreshRate(environmentOptions.GetRenderRefreshRate());
131
132   // Set the thread-synchronization interface on the render-surface
133   Dali::RenderSurfaceInterface* currentSurface = mAdaptorInterfaces.GetRenderSurfaceInterface();
134   if(currentSurface)
135   {
136     currentSurface->SetThreadSynchronization(*this);
137   }
138
139   mSleepTrigger = TriggerEventFactory::CreateTriggerEvent(MakeCallback(this, &CombinedUpdateRenderController::ProcessSleepRequest), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER);
140 }
141
142 CombinedUpdateRenderController::~CombinedUpdateRenderController()
143 {
144   LOG_EVENT_TRACE;
145
146   Stop();
147
148   delete mPreRenderCallback;
149   delete mSleepTrigger;
150 }
151
152 void CombinedUpdateRenderController::Initialize()
153 {
154   LOG_EVENT_TRACE;
155
156   // Ensure Update/Render Thread not already created
157   DALI_ASSERT_ALWAYS(!mUpdateRenderThread);
158
159   // Create Update/Render Thread
160   ConditionalWait::ScopedLock lock(mGraphicsInitializeWait);
161   mUpdateRenderThread = new pthread_t();
162   int error           = pthread_create(mUpdateRenderThread, NULL, InternalUpdateRenderThreadEntryFunc, this);
163   DALI_ASSERT_ALWAYS(!error && "Return code from pthread_create() when creating UpdateRenderThread");
164
165   // The Update/Render thread will now run and initialise the graphics interface etc. and will then wait for Start to be called
166   // When this function returns, the application initialisation on the event thread should occur
167 }
168
169 void CombinedUpdateRenderController::Start()
170 {
171   LOG_EVENT_TRACE;
172
173   DALI_ASSERT_ALWAYS(!mRunning && mUpdateRenderThread);
174
175   // Wait until all threads created in Initialise are up and running
176   for(unsigned int i = 0; i < CREATED_THREAD_COUNT; ++i)
177   {
178     mEventThreadSemaphore.Acquire();
179   }
180
181   mRunning = TRUE;
182
183   LOG_EVENT("Startup Complete, starting Update/Render Thread");
184
185   RunUpdateRenderThread(CONTINUOUS, AnimationProgression::NONE, UpdateMode::NORMAL);
186
187   Dali::RenderSurfaceInterface* currentSurface = mAdaptorInterfaces.GetRenderSurfaceInterface();
188   if(currentSurface)
189   {
190     currentSurface->StartRender();
191   }
192
193   DALI_LOG_RELEASE_INFO("CombinedUpdateRenderController::Start\n");
194 }
195
196 void CombinedUpdateRenderController::Pause()
197 {
198   LOG_EVENT_TRACE;
199
200   mRunning = FALSE;
201
202   PauseUpdateRenderThread();
203
204   AddPerformanceMarker(PerformanceInterface::PAUSED);
205
206   DALI_LOG_RELEASE_INFO("CombinedUpdateRenderController::Pause\n");
207 }
208
209 void CombinedUpdateRenderController::Resume()
210 {
211   LOG_EVENT_TRACE;
212
213   if(!mRunning && IsUpdateRenderThreadPaused())
214   {
215     LOG_EVENT("Resuming");
216
217     RunUpdateRenderThread(CONTINUOUS, AnimationProgression::USE_ELAPSED_TIME, UpdateMode::NORMAL);
218
219     AddPerformanceMarker(PerformanceInterface::RESUME);
220
221     mRunning               = TRUE;
222     mForceClear            = TRUE;
223     mFirstFrameAfterResume = TRUE;
224
225     DALI_LOG_RELEASE_INFO("CombinedUpdateRenderController::Resume\n");
226   }
227   else
228   {
229     DALI_LOG_RELEASE_INFO("CombinedUpdateRenderController::Resume: Already resumed [%d, %d, %d]\n", mRunning, mUpdateRenderRunCount, mUpdateRenderThreadCanSleep);
230   }
231 }
232
233 void CombinedUpdateRenderController::Stop()
234 {
235   LOG_EVENT_TRACE;
236
237   // Stop Rendering and the Update/Render Thread
238   Dali::RenderSurfaceInterface* currentSurface = mAdaptorInterfaces.GetRenderSurfaceInterface();
239   if(currentSurface)
240   {
241     currentSurface->StopRender();
242   }
243
244   StopUpdateRenderThread();
245
246   if(mUpdateRenderThread)
247   {
248     LOG_EVENT("Destroying UpdateRenderThread");
249
250     // wait for the thread to finish
251     pthread_join(*mUpdateRenderThread, NULL);
252
253     delete mUpdateRenderThread;
254     mUpdateRenderThread = NULL;
255   }
256
257   mRunning = FALSE;
258
259   DALI_LOG_RELEASE_INFO("CombinedUpdateRenderController::Stop\n");
260 }
261
262 void CombinedUpdateRenderController::RequestUpdate()
263 {
264   LOG_EVENT_TRACE;
265
266   // Increment the update-request count to the maximum
267   if(mUpdateRequestCount < MAXIMUM_UPDATE_REQUESTS)
268   {
269     ++mUpdateRequestCount;
270   }
271
272   if(mRunning && IsUpdateRenderThreadPaused())
273   {
274     LOG_EVENT("Processing");
275
276     RunUpdateRenderThread(CONTINUOUS, AnimationProgression::NONE, UpdateMode::NORMAL);
277   }
278
279   ConditionalWait::ScopedLock updateLock(mUpdateRenderThreadWaitCondition);
280   mPendingRequestUpdate = TRUE;
281 }
282
283 void CombinedUpdateRenderController::RequestUpdateOnce(UpdateMode updateMode)
284 {
285   // Increment the update-request count to the maximum
286   if(mUpdateRequestCount < MAXIMUM_UPDATE_REQUESTS)
287   {
288     ++mUpdateRequestCount;
289   }
290
291   if(IsUpdateRenderThreadPaused() || updateMode == UpdateMode::FORCE_RENDER)
292   {
293     LOG_EVENT_TRACE;
294
295     // Run Update/Render once
296     RunUpdateRenderThread(ONCE, AnimationProgression::NONE, updateMode);
297   }
298 }
299
300 void CombinedUpdateRenderController::ReplaceSurface(Dali::RenderSurfaceInterface* newSurface)
301 {
302   LOG_EVENT_TRACE;
303
304   if(mUpdateRenderThread)
305   {
306     // Set the ThreadSyncronizationInterface on the new surface
307     newSurface->SetThreadSynchronization(*this);
308
309     LOG_EVENT("Starting to replace the surface, event-thread blocked");
310
311     // Start replacing the surface.
312     {
313       ConditionalWait::ScopedLock lock(mUpdateRenderThreadWaitCondition);
314       mPostRendering = FALSE; // Clear the post-rendering flag as Update/Render thread will replace the surface now
315       mNewSurface    = newSurface;
316       mUpdateRenderThreadWaitCondition.Notify(lock);
317     }
318
319     // Wait until the surface has been replaced
320     mSurfaceSemaphore.Acquire();
321
322     LOG_EVENT("Surface replaced, event-thread continuing");
323   }
324 }
325
326 void CombinedUpdateRenderController::DeleteSurface(Dali::RenderSurfaceInterface* surface)
327 {
328   LOG_EVENT_TRACE;
329
330   if(mUpdateRenderThread)
331   {
332     LOG_EVENT("Starting to delete the surface, event-thread blocked");
333
334     // Start replacing the surface.
335     {
336       ConditionalWait::ScopedLock lock(mUpdateRenderThreadWaitCondition);
337       mPostRendering  = FALSE; // Clear the post-rendering flag as Update/Render thread will delete the surface now
338       mDeletedSurface = surface;
339       mUpdateRenderThreadWaitCondition.Notify(lock);
340     }
341
342     // Wait until the surface has been deleted
343     mSurfaceSemaphore.Acquire();
344
345     LOG_EVENT("Surface deleted, event-thread continuing");
346   }
347 }
348
349 void CombinedUpdateRenderController::WaitForGraphicsInitialization()
350 {
351   ConditionalWait::ScopedLock lk(mGraphicsInitializeWait);
352   LOG_EVENT_TRACE;
353
354   if(mUpdateRenderThread)
355   {
356     LOG_EVENT("Waiting for graphics initialisation, event-thread blocked");
357
358     // Wait until the graphics has been initialised
359     mGraphicsInitializeWait.Wait(lk);
360
361     LOG_EVENT("graphics initialised, event-thread continuing");
362   }
363 }
364
365 void CombinedUpdateRenderController::ResizeSurface()
366 {
367   LOG_EVENT_TRACE;
368
369   LOG_EVENT("Resize the surface");
370
371   {
372     ConditionalWait::ScopedLock lock(mUpdateRenderThreadWaitCondition);
373     // Surface is resized and the surface resized count is increased.
374     mSurfaceResized++;
375     mUpdateRenderThreadWaitCondition.Notify(lock);
376   }
377 }
378
379 void CombinedUpdateRenderController::SetRenderRefreshRate(unsigned int numberOfFramesPerRender)
380 {
381   // Not protected by lock, but written to rarely so not worth adding a lock when reading
382   mDefaultFrameDelta                = numberOfFramesPerRender * DEFAULT_FRAME_DURATION_IN_SECONDS;
383   mDefaultFrameDurationMilliseconds = uint64_t(numberOfFramesPerRender) * DEFAULT_FRAME_DURATION_IN_MILLISECONDS;
384   mDefaultFrameDurationNanoseconds  = uint64_t(numberOfFramesPerRender) * DEFAULT_FRAME_DURATION_IN_NANOSECONDS;
385   mDefaultHalfFrameNanoseconds      = mDefaultFrameDurationNanoseconds / 2u;
386
387   LOG_EVENT("mDefaultFrameDelta(%.6f), mDefaultFrameDurationMilliseconds(%lld), mDefaultFrameDurationNanoseconds(%lld)", mDefaultFrameDelta, mDefaultFrameDurationMilliseconds, mDefaultFrameDurationNanoseconds);
388 }
389
390 void CombinedUpdateRenderController::SetPreRenderCallback(CallbackBase* callback)
391 {
392   LOG_EVENT_TRACE;
393   LOG_EVENT("Set PreRender Callback");
394
395   ConditionalWait::ScopedLock updateLock(mUpdateRenderThreadWaitCondition);
396   if(mPreRenderCallback)
397   {
398     delete mPreRenderCallback;
399   }
400   mPreRenderCallback = callback;
401 }
402
403 void CombinedUpdateRenderController::AddSurface(Dali::RenderSurfaceInterface* surface)
404 {
405   LOG_EVENT_TRACE;
406   LOG_EVENT("Surface is added");
407   if(mUpdateRenderThread)
408   {
409     // Set the ThreadSyncronizationInterface on the added surface
410     surface->SetThreadSynchronization(*this);
411   }
412 }
413
414 int32_t CombinedUpdateRenderController::GetThreadId() const
415 {
416   return mThreadId;
417 }
418
419 ///////////////////////////////////////////////////////////////////////////////////////////////////
420 // EVENT THREAD
421 ///////////////////////////////////////////////////////////////////////////////////////////////////
422
423 void CombinedUpdateRenderController::RunUpdateRenderThread(int numberOfCycles, AnimationProgression animationProgression, UpdateMode updateMode)
424 {
425   ConditionalWait::ScopedLock lock(mUpdateRenderThreadWaitCondition);
426
427   switch(mThreadMode)
428   {
429     case ThreadMode::NORMAL:
430     {
431       mUpdateRenderRunCount    = numberOfCycles;
432       mUseElapsedTimeAfterWait = (animationProgression == AnimationProgression::USE_ELAPSED_TIME);
433       break;
434     }
435     case ThreadMode::RUN_IF_REQUESTED:
436     {
437       if(updateMode != UpdateMode::FORCE_RENDER)
438       {
439         // Render only if the update mode is FORCE_RENDER which means the application requests it.
440         // We don't want to awake the update thread.
441         return;
442       }
443
444       mUpdateRenderRunCount++;         // Increase the update request count
445       mUseElapsedTimeAfterWait = TRUE; // The elapsed time should be used. We want animations to proceed.
446       break;
447     }
448   }
449
450   mUpdateRenderThreadCanSleep = FALSE;
451   mUploadWithoutRendering     = (updateMode == UpdateMode::SKIP_RENDER);
452   LOG_COUNTER_EVENT("mUpdateRenderRunCount: %d, mUseElapsedTimeAfterWait: %d", mUpdateRenderRunCount, mUseElapsedTimeAfterWait);
453   mUpdateRenderThreadWaitCondition.Notify(lock);
454 }
455
456 void CombinedUpdateRenderController::PauseUpdateRenderThread()
457 {
458   ConditionalWait::ScopedLock lock(mUpdateRenderThreadWaitCondition);
459   mUpdateRenderRunCount = 0;
460 }
461
462 void CombinedUpdateRenderController::StopUpdateRenderThread()
463 {
464   ConditionalWait::ScopedLock lock(mUpdateRenderThreadWaitCondition);
465   mDestroyUpdateRenderThread = TRUE;
466   mUpdateRenderThreadWaitCondition.Notify(lock);
467 }
468
469 bool CombinedUpdateRenderController::IsUpdateRenderThreadPaused()
470 {
471   ConditionalWait::ScopedLock lock(mUpdateRenderThreadWaitCondition);
472
473   if(mThreadMode == ThreadMode::RUN_IF_REQUESTED)
474   {
475     return !mRunning || mUpdateRenderThreadCanSleep;
476   }
477
478   return (mUpdateRenderRunCount != CONTINUOUS) || // Report paused if NOT continuously running
479          mUpdateRenderThreadCanSleep;             // Report paused if sleeping
480 }
481
482 void CombinedUpdateRenderController::ProcessSleepRequest()
483 {
484   LOG_EVENT_TRACE;
485
486   // Decrement Update request count
487   if(mUpdateRequestCount > 0)
488   {
489     --mUpdateRequestCount;
490   }
491
492   // Can sleep if our update-request count is 0
493   // Update/Render thread can choose to carry on updating if it determines more update/renders are required
494   if(mUpdateRequestCount == 0)
495   {
496     LOG_EVENT("Going to sleep");
497
498     ConditionalWait::ScopedLock lock(mUpdateRenderThreadWaitCondition);
499     mUpdateRenderThreadCanSleep = TRUE;
500   }
501 }
502
503 ///////////////////////////////////////////////////////////////////////////////////////////////////
504 // UPDATE/RENDER THREAD
505 ///////////////////////////////////////////////////////////////////////////////////////////////////
506
507 void CombinedUpdateRenderController::UpdateRenderThread()
508 {
509   ThreadSettings::SetThreadName("RenderThread\0");
510   mThreadId = ThreadSettings::GetThreadId();
511
512   // Install a function for logging
513   mEnvironmentOptions.InstallLogFunction();
514
515   // Install a function for tracing
516   mEnvironmentOptions.InstallTraceFunction();
517
518   TRACE_UPDATE_RENDER_BEGIN("DALI_RENDER_THREAD_INIT");
519
520   LOG_UPDATE_RENDER("THREAD CREATED");
521
522   // Initialize graphics
523   GraphicsInterface& graphics = mAdaptorInterfaces.GetGraphicsInterface();
524   graphics.Initialize();
525
526   Dali::DisplayConnection& displayConnection = mAdaptorInterfaces.GetDisplayConnectionInterface();
527   displayConnection.Initialize(); //@todo Move InitializeGraphics code into graphics implementation
528
529   // Setup graphics controller into upload manager.
530   GetImplementation(mTextureUploadManager).InitalizeGraphicsController(graphics.GetController());
531
532   NotifyGraphicsInitialised();
533
534   //@todo Vk swaps this around, but we need to support surfaceless context for multi-window
535   graphics.ConfigureSurface(mAdaptorInterfaces.GetRenderSurfaceInterface());
536
537   // Tell core it has a context
538   mCore.ContextCreated();
539
540   NotifyThreadInitialised();
541
542   // Initialize and create graphics resource for the shared context.
543   WindowContainer windows;
544   mAdaptorInterfaces.GetWindowContainerInterface(windows);
545
546   for(auto&& window : windows)
547   {
548     Dali::Integration::Scene      scene         = window->GetScene();
549     Dali::RenderSurfaceInterface* windowSurface = window->GetSurface();
550
551     if(scene && windowSurface)
552     {
553       windowSurface->InitializeGraphics();
554     }
555   }
556
557   // Update time
558   uint64_t lastFrameTime;
559   TimeService::GetNanoseconds(lastFrameTime);
560   uint64_t lastMemPoolLogTime = lastFrameTime;
561
562   LOG_UPDATE_RENDER("THREAD INITIALISED");
563
564   bool     useElapsedTime     = true;
565   bool     updateRequired     = true;
566   uint64_t timeToSleepUntil   = 0;
567   int      extraFramesDropped = 0;
568
569   const uint64_t memPoolInterval = 1e9 * float(mEnvironmentOptions.GetMemoryPoolInterval());
570
571   const unsigned int renderToFboInterval = mEnvironmentOptions.GetRenderToFboInterval();
572   const bool         renderToFboEnabled  = 0u != renderToFboInterval;
573   unsigned int       frameCount          = 0u;
574
575   TRACE_UPDATE_RENDER_END("DALI_RENDER_THREAD_INIT");
576
577   if(Integration::ShaderPrecompiler::Get().IsEnable())
578   {
579     std::vector<RawShaderData> precompiledShaderList;
580     Integration::ShaderPrecompiler::Get().GetPrecompileShaderList(precompiledShaderList);
581     DALI_LOG_RELEASE_INFO("ShaderPrecompiler[ENABLE], list size:%d \n",precompiledShaderList.size());
582     for(auto precompiledShader = precompiledShaderList.begin(); precompiledShader != precompiledShaderList.end(); ++precompiledShader)
583     {
584       auto numberOfPrecomipledShader = precompiledShader->shaderCount;
585       for(int i= 0; i<numberOfPrecomipledShader; ++i)
586       {
587         auto vertexShader   = std::string(graphics.GetController().GetGlAbstraction().GetVertexShaderPrefix() + precompiledShader->vertexPrefix[i].data() + precompiledShader->vertexShader.data());
588         auto fragmentShader = std::string(graphics.GetController().GetGlAbstraction().GetFragmentShaderPrefix() + precompiledShader->fragmentPrefix[i].data() + precompiledShader->fragmentShader.data());
589         mCore.PreCompileShader(vertexShader.data(), fragmentShader.data());
590       }
591       DALI_LOG_RELEASE_INFO("ShaderPrecompiler[ENABLE], shader count :%d \n",numberOfPrecomipledShader);
592     }
593   }
594   else
595   {
596     DALI_LOG_RELEASE_INFO("ShaderPrecompiler[DISABLE] \n");
597   }
598
599   while(UpdateRenderReady(useElapsedTime, updateRequired, timeToSleepUntil))
600   {
601     LOG_UPDATE_RENDER_TRACE;
602     TRACE_UPDATE_RENDER_SCOPE("DALI_UPDATE_RENDER");
603
604     // For thread safe
605     bool                          uploadOnly     = mUploadWithoutRendering;
606     unsigned int                  surfaceResized = mSurfaceResized;
607     Dali::RenderSurfaceInterface* deletedSurface = ShouldSurfaceBeDeleted();
608
609     // Performance statistics are logged upon a VSYNC tick so use this point for a VSync marker
610     AddPerformanceMarker(PerformanceInterface::VSYNC);
611
612     uint64_t currentFrameStartTime = 0;
613     TimeService::GetNanoseconds(currentFrameStartTime);
614
615     uint64_t timeSinceLastFrame = currentFrameStartTime - lastFrameTime;
616
617     // Optional FPS Tracking when continuously rendering
618     if(useElapsedTime && mFpsTracker.Enabled())
619     {
620       float absoluteTimeSinceLastRender = timeSinceLastFrame * NANOSECONDS_TO_SECOND;
621       mFpsTracker.Track(absoluteTimeSinceLastRender);
622     }
623
624     lastFrameTime = currentFrameStartTime; // Store frame start time
625
626     //////////////////////////////
627     // REPLACE SURFACE
628     //////////////////////////////
629
630     Dali::RenderSurfaceInterface* newSurface = ShouldSurfaceBeReplaced();
631     if(DALI_UNLIKELY(newSurface))
632     {
633       LOG_UPDATE_RENDER_TRACE_FMT("Replacing Surface");
634       // This is designed for replacing pixmap surfaces, but should work for window as well
635       // we need to delete the surface and renderable (pixmap / window)
636       // Then create a new pixmap/window and new surface
637       // If the new surface has a different display connection, then the context will be lost
638       mAdaptorInterfaces.GetDisplayConnectionInterface().Initialize();
639       graphics.ActivateSurfaceContext(newSurface);
640       // TODO: ReplaceGraphicsSurface doesn't work, InitializeGraphics()
641       // already creates new surface window, the surface and the context.
642       // We probably don't need ReplaceGraphicsSurface at all.
643       // newSurface->ReplaceGraphicsSurface();
644       SurfaceReplaced();
645     }
646
647     //////////////////////////////
648     // TextureUploadRequest (phase #1)
649     //////////////////////////////
650
651     // Upload requested resources after resource context activated.
652     graphics.ActivateResourceContext();
653
654     const bool textureUploaded = mTextureUploadManager.ResourceUpload();
655
656     // Update & Render forcely if there exist some uploaded texture.
657     uploadOnly = textureUploaded ? false : uploadOnly;
658
659     const bool isRenderingToFbo = renderToFboEnabled && ((0u == frameCount) || (0u != frameCount % renderToFboInterval));
660     ++frameCount;
661
662     //////////////////////////////
663     // UPDATE
664     //////////////////////////////
665
666     const uint32_t currentTime   = static_cast<uint32_t>(currentFrameStartTime / NANOSECONDS_PER_MILLISECOND);
667     const uint32_t nextFrameTime = currentTime + static_cast<uint32_t>(mDefaultFrameDurationMilliseconds);
668
669     uint64_t noOfFramesSinceLastUpdate = 1;
670     float    frameDelta                = 0.0f;
671     if(useElapsedTime)
672     {
673       if(mThreadMode == ThreadMode::RUN_IF_REQUESTED)
674       {
675         extraFramesDropped = 0;
676         while(timeSinceLastFrame >= mDefaultFrameDurationNanoseconds)
677         {
678           timeSinceLastFrame -= mDefaultFrameDurationNanoseconds;
679           extraFramesDropped++;
680         }
681       }
682
683       // If using the elapsed time, then calculate frameDelta as a multiple of mDefaultFrameDelta
684       noOfFramesSinceLastUpdate += extraFramesDropped;
685
686       frameDelta = mDefaultFrameDelta * noOfFramesSinceLastUpdate;
687     }
688     LOG_UPDATE_RENDER("timeSinceLastFrame(%llu) noOfFramesSinceLastUpdate(%u) frameDelta(%.6f)", timeSinceLastFrame, noOfFramesSinceLastUpdate, frameDelta);
689
690     Integration::UpdateStatus updateStatus;
691
692     AddPerformanceMarker(PerformanceInterface::UPDATE_START);
693     TRACE_UPDATE_RENDER_BEGIN("DALI_UPDATE");
694     mCore.Update(frameDelta,
695                  currentTime,
696                  nextFrameTime,
697                  updateStatus,
698                  renderToFboEnabled,
699                  isRenderingToFbo,
700                  uploadOnly);
701     TRACE_UPDATE_RENDER_END("DALI_UPDATE");
702     AddPerformanceMarker(PerformanceInterface::UPDATE_END);
703
704     unsigned int keepUpdatingStatus = updateStatus.KeepUpdating();
705
706     // Tell the event-thread to wake up (if asleep) and send a notification event to Core if required
707     if(updateStatus.NeedsNotification())
708     {
709       mNotificationTrigger.Trigger();
710       LOG_UPDATE_RENDER("Notification Triggered");
711     }
712
713     // Optional logging of update/render status
714     mUpdateStatusLogger.Log(keepUpdatingStatus);
715
716     //////////////////////////////
717     // RENDER
718     //////////////////////////////
719
720     graphics.FrameStart();
721     mAdaptorInterfaces.GetDisplayConnectionInterface().ConsumeEvents();
722
723     if(mPreRenderCallback != NULL)
724     {
725       bool keepCallback = CallbackBase::ExecuteReturn<bool>(*mPreRenderCallback);
726       if(!keepCallback)
727       {
728         delete mPreRenderCallback;
729         mPreRenderCallback = NULL;
730       }
731     }
732
733     //////////////////////////////
734     // TextureUploadRequest (phase #2)
735     //////////////////////////////
736
737     // Upload requested resources after resource context activated.
738     graphics.ActivateResourceContext();
739
740     // Since uploadOnly value used at Update side, we should not change uploadOnly value now even some textures are uploaded.
741     mTextureUploadManager.ResourceUpload();
742
743     if(mFirstFrameAfterResume)
744     {
745       // mFirstFrameAfterResume is set to true when the thread is resumed
746       // Let graphics know the first frame after thread initialized or resumed.
747       graphics.SetFirstFrameAfterResume();
748       mFirstFrameAfterResume = FALSE;
749     }
750
751     Integration::RenderStatus renderStatus;
752
753     AddPerformanceMarker(PerformanceInterface::RENDER_START);
754     TRACE_UPDATE_RENDER_BEGIN("DALI_RENDER");
755
756     // Upload shared resources
757     TRACE_UPDATE_RENDER_BEGIN("DALI_PRE_RENDER");
758     mCore.PreRender(renderStatus, mForceClear);
759     TRACE_UPDATE_RENDER_END("DALI_PRE_RENDER");
760
761     if(!uploadOnly || surfaceResized)
762     {
763       // Go through each window
764       windows.clear();
765       mAdaptorInterfaces.GetWindowContainerInterface(windows);
766
767       for(auto&& window : windows)
768       {
769         Dali::Integration::Scene      scene         = window->GetScene();
770         Dali::RenderSurfaceInterface* windowSurface = window->GetSurface();
771
772         if(scene && windowSurface)
773         {
774           TRACE_UPDATE_RENDER_SCOPE("DALI_RENDER_SCENE");
775           Integration::RenderStatus windowRenderStatus;
776
777           const bool sceneSurfaceResized = scene.IsSurfaceRectChanged();
778
779           // clear previous frame damaged render items rects, buffer history is tracked on surface level
780           mDamagedRects.clear();
781
782           // Collect damage rects
783           mCore.PreRender(scene, mDamagedRects);
784
785           // Render off-screen frame buffers first if any
786           mCore.RenderScene(windowRenderStatus, scene, true);
787
788           Rect<int> clippingRect; // Empty for fbo rendering
789
790           // Switch to the context of the surface, merge damaged areas for previous frames
791           windowSurface->PreRender(sceneSurfaceResized, mDamagedRects, clippingRect); // Switch GL context
792
793           // Render the surface
794           mCore.RenderScene(windowRenderStatus, scene, false, clippingRect);
795
796           // Buffer swapping now happens when the surface render target is presented.
797
798           // If surface is resized, the surface resized count is decreased.
799           if(DALI_UNLIKELY(sceneSurfaceResized))
800           {
801             SurfaceResized();
802           }
803         }
804       }
805     }
806
807     TRACE_UPDATE_RENDER_BEGIN("DALI_POST_RENDER");
808     if(!uploadOnly)
809     {
810       graphics.PostRender();
811     }
812
813     mCore.PostRender();
814     TRACE_UPDATE_RENDER_END("DALI_POST_RENDER");
815
816     //////////////////////////////
817     // DELETE SURFACE
818     //////////////////////////////
819     if(DALI_UNLIKELY(deletedSurface))
820     {
821       LOG_UPDATE_RENDER_TRACE_FMT("Deleting Surface");
822
823       deletedSurface->DestroySurface();
824
825       SurfaceDeleted();
826     }
827
828     TRACE_UPDATE_RENDER_END("DALI_RENDER");
829     AddPerformanceMarker(PerformanceInterface::RENDER_END);
830
831     // if the memory pool interval is set and has elapsed, log the graphics memory pools
832     if(0 < memPoolInterval && memPoolInterval < lastFrameTime - lastMemPoolLogTime)
833     {
834       lastMemPoolLogTime = lastFrameTime;
835       graphics.LogMemoryPools();
836     }
837
838     mForceClear = false;
839
840     // Trigger event thread to request Update/Render thread to sleep if update not required
841     if((Integration::KeepUpdating::NOT_REQUESTED == keepUpdatingStatus) && !renderStatus.NeedsUpdate())
842     {
843       mSleepTrigger->Trigger();
844       updateRequired = false;
845       LOG_UPDATE_RENDER("Sleep Triggered");
846     }
847     else
848     {
849       updateRequired = true;
850     }
851
852     //////////////////////////////
853     // FRAME TIME
854     //////////////////////////////
855
856     extraFramesDropped = 0;
857
858     if(timeToSleepUntil == 0)
859     {
860       // If this is the first frame after the thread is initialized or resumed, we
861       // use the actual time the current frame starts from to calculate the time to
862       // sleep until the next frame.
863       timeToSleepUntil = currentFrameStartTime + mDefaultFrameDurationNanoseconds;
864     }
865     else
866     {
867       // Otherwise, always use the sleep-until time calculated in the last frame to
868       // calculate the time to sleep until the next frame. In this way, if there is
869       // any time gap between the current frame and the next frame, or if update or
870       // rendering in the current frame takes too much time so that the specified
871       // sleep-until time has already passed, it will try to keep the frames syncing
872       // by shortening the duration of the next frame.
873       timeToSleepUntil += mDefaultFrameDurationNanoseconds;
874
875       // Check the current time at the end of the frame
876       uint64_t currentFrameEndTime = 0;
877       TimeService::GetNanoseconds(currentFrameEndTime);
878       while(currentFrameEndTime > timeToSleepUntil + mDefaultFrameDurationNanoseconds)
879       {
880         // We are more than one frame behind already, so just drop the next frames
881         // until the sleep-until time is later than the current time so that we can
882         // catch up.
883         timeToSleepUntil += mDefaultFrameDurationNanoseconds;
884         extraFramesDropped++;
885       }
886     }
887
888     // Render to FBO is intended to measure fps above 60 so sleep is not wanted.
889     if(0u == renderToFboInterval)
890     {
891       TRACE_UPDATE_RENDER_SCOPE("DALI_UPDATE_RENDER_SLEEP");
892       // Sleep until at least the the default frame duration has elapsed. This will return immediately if the specified end-time has already passed.
893       TimeService::SleepUntil(timeToSleepUntil);
894     }
895   }
896   TRACE_UPDATE_RENDER_BEGIN("DALI_RENDER_THREAD_FINISH");
897
898   // Inform core of context destruction
899   mCore.ContextDestroyed();
900
901   windows.clear();
902   mAdaptorInterfaces.GetWindowContainerInterface(windows);
903
904   // Destroy surfaces
905   for(auto&& window : windows)
906   {
907     Dali::RenderSurfaceInterface* surface = window->GetSurface();
908     surface->DestroySurface();
909   }
910
911   graphics.Shutdown();
912
913   LOG_UPDATE_RENDER("THREAD DESTROYED");
914
915   TRACE_UPDATE_RENDER_END("DALI_RENDER_THREAD_FINISH");
916
917   // Uninstall the logging function
918   mEnvironmentOptions.UnInstallLogFunction();
919 }
920
921 bool CombinedUpdateRenderController::UpdateRenderReady(bool& useElapsedTime, bool updateRequired, uint64_t& timeToSleepUntil)
922 {
923   useElapsedTime = true;
924
925   ConditionalWait::ScopedLock updateLock(mUpdateRenderThreadWaitCondition);
926   while((!mUpdateRenderRunCount ||                                                      // Should try to wait if event-thread has paused the Update/Render thread
927          (mUpdateRenderThreadCanSleep && !updateRequired && !mPendingRequestUpdate)) && // Ensure we wait if we're supposed to be sleeping AND do not require another update
928         !mDestroyUpdateRenderThread &&                                                  // Ensure we don't wait if the update-render-thread is supposed to be destroyed
929         !mNewSurface &&                                                                 // Ensure we don't wait if we need to replace the surface
930         !mDeletedSurface &&                                                             // Ensure we don't wait if we need to delete the surface
931         !mSurfaceResized)                                                               // Ensure we don't wait if we need to resize the surface
932   {
933     LOG_UPDATE_RENDER("WAIT: mUpdateRenderRunCount:       %d", mUpdateRenderRunCount);
934     LOG_UPDATE_RENDER("      mUpdateRenderThreadCanSleep: %d, updateRequired: %d, mPendingRequestUpdate: %d", mUpdateRenderThreadCanSleep, updateRequired, mPendingRequestUpdate);
935     LOG_UPDATE_RENDER("      mDestroyUpdateRenderThread:  %d", mDestroyUpdateRenderThread);
936     LOG_UPDATE_RENDER("      mNewSurface:                 %d", mNewSurface);
937     LOG_UPDATE_RENDER("      mDeletedSurface:             %d", mDeletedSurface);
938     LOG_UPDATE_RENDER("      mSurfaceResized:             %d", mSurfaceResized);
939
940     // Reset the time when the thread is waiting, so the sleep-until time for
941     // the first frame after resuming should be based on the actual start time
942     // of the first frame.
943     timeToSleepUntil = 0;
944
945     TRACE_UPDATE_RENDER_BEGIN("DALI_UPDATE_RENDER_THREAD_WAIT_CONDITION");
946     mUpdateRenderThreadWaitCondition.Wait(updateLock);
947     TRACE_UPDATE_RENDER_END("DALI_UPDATE_RENDER_THREAD_WAIT_CONDITION");
948
949     if(!mUseElapsedTimeAfterWait)
950     {
951       useElapsedTime = false;
952     }
953   }
954
955   LOG_COUNTER_UPDATE_RENDER("mUpdateRenderRunCount:       %d", mUpdateRenderRunCount);
956   LOG_COUNTER_UPDATE_RENDER("mUpdateRenderThreadCanSleep: %d, updateRequired: %d, mPendingRequestUpdate: %d", mUpdateRenderThreadCanSleep, updateRequired, mPendingRequestUpdate);
957   LOG_COUNTER_UPDATE_RENDER("mDestroyUpdateRenderThread:  %d", mDestroyUpdateRenderThread);
958   LOG_COUNTER_UPDATE_RENDER("mNewSurface:                 %d", mNewSurface);
959   LOG_COUNTER_UPDATE_RENDER("mDeletedSurface:             %d", mDeletedSurface);
960   LOG_COUNTER_UPDATE_RENDER("mSurfaceResized:             %d", mSurfaceResized);
961
962   mUseElapsedTimeAfterWait    = FALSE;
963   mUpdateRenderThreadCanSleep = FALSE;
964   mPendingRequestUpdate       = FALSE;
965
966   // If we've been asked to run Update/Render cycles a finite number of times then decrement so we wait after the
967   // requested number of cycles
968   if(mUpdateRenderRunCount > 0)
969   {
970     --mUpdateRenderRunCount;
971   }
972
973   // Keep the update-render thread alive if this thread is NOT to be destroyed
974   return !mDestroyUpdateRenderThread;
975 }
976
977 Dali::RenderSurfaceInterface* CombinedUpdateRenderController::ShouldSurfaceBeReplaced()
978 {
979   ConditionalWait::ScopedLock lock(mUpdateRenderThreadWaitCondition);
980
981   Dali::RenderSurfaceInterface* newSurface = mNewSurface;
982   mNewSurface                              = NULL;
983
984   return newSurface;
985 }
986
987 void CombinedUpdateRenderController::SurfaceReplaced()
988 {
989   // Just increment the semaphore
990   mSurfaceSemaphore.Release(1);
991 }
992
993 Dali::RenderSurfaceInterface* CombinedUpdateRenderController::ShouldSurfaceBeDeleted()
994 {
995   ConditionalWait::ScopedLock lock(mUpdateRenderThreadWaitCondition);
996
997   Dali::RenderSurfaceInterface* deletedSurface = mDeletedSurface;
998   mDeletedSurface                              = NULL;
999
1000   return deletedSurface;
1001 }
1002
1003 void CombinedUpdateRenderController::SurfaceDeleted()
1004 {
1005   // Just increment the semaphore
1006   mSurfaceSemaphore.Release(1);
1007 }
1008
1009 void CombinedUpdateRenderController::SurfaceResized()
1010 {
1011   ConditionalWait::ScopedLock lock(mUpdateRenderThreadWaitCondition);
1012   if(mSurfaceResized)
1013   {
1014     mSurfaceResized--;
1015   }
1016 }
1017
1018 ///////////////////////////////////////////////////////////////////////////////////////////////////
1019 // ALL THREADS
1020 ///////////////////////////////////////////////////////////////////////////////////////////////////
1021
1022 void CombinedUpdateRenderController::NotifyThreadInitialised()
1023 {
1024   // Just increment the semaphore
1025   mEventThreadSemaphore.Release(1);
1026 }
1027
1028 void CombinedUpdateRenderController::NotifyGraphicsInitialised()
1029 {
1030   mGraphicsInitializeWait.Notify();
1031 }
1032
1033 void CombinedUpdateRenderController::AddPerformanceMarker(PerformanceInterface::MarkerType type)
1034 {
1035   if(mPerformanceInterface)
1036   {
1037     mPerformanceInterface->AddMarker(type);
1038   }
1039 }
1040
1041 /////////////////////////////////////////////////////////////////////////////////////////////////
1042 // POST RENDERING: EVENT THREAD
1043 /////////////////////////////////////////////////////////////////////////////////////////////////
1044
1045 void CombinedUpdateRenderController::PostRenderComplete()
1046 {
1047   ConditionalWait::ScopedLock lock(mUpdateRenderThreadWaitCondition);
1048   mPostRendering = FALSE;
1049   mUpdateRenderThreadWaitCondition.Notify(lock);
1050 }
1051
1052 ///////////////////////////////////////////////////////////////////////////////////////////////////
1053 // POST RENDERING: RENDER THREAD
1054 ///////////////////////////////////////////////////////////////////////////////////////////////////
1055
1056 void CombinedUpdateRenderController::PostRenderStarted()
1057 {
1058   ConditionalWait::ScopedLock lock(mUpdateRenderThreadWaitCondition);
1059   mPostRendering = TRUE;
1060 }
1061
1062 void CombinedUpdateRenderController::PostRenderWaitForCompletion()
1063 {
1064   ConditionalWait::ScopedLock lock(mUpdateRenderThreadWaitCondition);
1065   while(mPostRendering &&
1066         !mNewSurface &&     // We should NOT wait if we're replacing the surface
1067         !mDeletedSurface && // We should NOT wait if we're deleting the surface
1068         !mDestroyUpdateRenderThread)
1069   {
1070     mUpdateRenderThreadWaitCondition.Wait(lock);
1071   }
1072 }
1073
1074 } // namespace Adaptor
1075
1076 } // namespace Internal
1077
1078 } // namespace Dali