Merge branch 'devel/master' into tizen
[platform/core/uifw/dali-adaptor.git] / dali / internal / window-system / common / window-render-surface.cpp
1 /*
2  * Copyright (c) 2020 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/window-system/common/window-render-surface.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali/integration-api/gl-abstraction.h>
23 #include <dali/integration-api/debug.h>
24
25 // INTERNAL INCLUDES
26 #include <dali/integration-api/adaptor-framework/thread-synchronization-interface.h>
27 #include <dali/integration-api/adaptor-framework/trigger-event-factory.h>
28 #include <dali/internal/adaptor/common/adaptor-impl.h>
29 #include <dali/internal/adaptor/common/adaptor-internal-services.h>
30 #include <dali/internal/graphics/gles/egl-graphics.h>
31 #include <dali/internal/graphics/gles/egl-implementation.h>
32 #include <dali/internal/window-system/common/window-base.h>
33 #include <dali/internal/window-system/common/window-factory.h>
34 #include <dali/internal/window-system/common/window-system.h>
35 #include <dali/internal/system/common/environment-variables.h>
36
37 namespace Dali
38 {
39 namespace Internal
40 {
41 namespace Adaptor
42 {
43
44 namespace
45 {
46
47 const int MINIMUM_DIMENSION_CHANGE( 1 ); ///< Minimum change for window to be considered to have moved
48
49 #if defined(DEBUG_ENABLED)
50 Debug::Filter* gWindowRenderSurfaceLogFilter = Debug::Filter::New(Debug::Verbose, false, "LOG_WINDOW_RENDER_SURFACE");
51 #endif
52
53 } // unnamed namespace
54
55 WindowRenderSurface::WindowRenderSurface( Dali::PositionSize positionSize, Any surface, bool isTransparent )
56 : mEGL( nullptr ),
57   mDisplayConnection( nullptr ),
58   mPositionSize( positionSize ),
59   mWindowBase(),
60   mThreadSynchronization( NULL ),
61   mRenderNotification( NULL ),
62   mRotationTrigger( NULL ),
63   mFrameRenderedTrigger(),
64   mGraphics( nullptr ),
65   mEGLSurface( nullptr ),
66   mEGLContext( nullptr ),
67   mColorDepth( isTransparent ? COLOR_DEPTH_32 : COLOR_DEPTH_24 ),
68   mOutputTransformedSignal(),
69   mFrameCallbackInfoContainer(),
70   mMutex(),
71   mRotationAngle( 0 ),
72   mScreenRotationAngle( 0 ),
73   mOwnSurface( false ),
74   mRotationSupported( false ),
75   mRotationFinished( true ),
76   mScreenRotationFinished( true ),
77   mResizeFinished( true ),
78   mDpiHorizontal( 0 ),
79   mDpiVertical( 0 )
80 {
81   DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "Creating Window\n" );
82   Initialize( surface );
83 }
84
85 WindowRenderSurface::~WindowRenderSurface()
86 {
87   if( mRotationTrigger )
88   {
89     delete mRotationTrigger;
90   }
91 }
92
93 void WindowRenderSurface::Initialize( Any surface )
94 {
95   // If width or height are zero, go full screen.
96   if ( (mPositionSize.width == 0) || (mPositionSize.height == 0) )
97   {
98     // Default window size == screen size
99     mPositionSize.x = 0;
100     mPositionSize.y = 0;
101     WindowSystem::GetScreenSize( mPositionSize.width, mPositionSize.height );
102   }
103
104   // Create a window base
105   auto windowFactory = Dali::Internal::Adaptor::GetWindowFactory();
106   mWindowBase = windowFactory->CreateWindowBase( mPositionSize, surface, ( mColorDepth == COLOR_DEPTH_32 ? true : false ) );
107
108   // Connect signals
109   mWindowBase->OutputTransformedSignal().Connect( this, &WindowRenderSurface::OutputTransformed );
110
111   // Check screen rotation
112   mScreenRotationAngle = mWindowBase->GetScreenRotationAngle();
113   if( mScreenRotationAngle != 0 )
114   {
115     mScreenRotationFinished = false;
116   }
117 }
118
119 Any WindowRenderSurface::GetNativeWindow()
120 {
121   return mWindowBase->GetNativeWindow();
122 }
123
124 int WindowRenderSurface::GetNativeWindowId()
125 {
126   return mWindowBase->GetNativeWindowId();
127 }
128
129 void WindowRenderSurface::Map()
130 {
131   mWindowBase->Show();
132 }
133
134 void WindowRenderSurface::SetRenderNotification( TriggerEventInterface* renderNotification )
135 {
136   mRenderNotification = renderNotification;
137 }
138
139 void WindowRenderSurface::SetTransparency( bool transparent )
140 {
141   mWindowBase->SetTransparency( transparent );
142 }
143
144 void WindowRenderSurface::RequestRotation( int angle, int width, int height )
145 {
146   if( !mRotationSupported )
147   {
148     DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::Rotate: Rotation is not supported!\n" );
149     return;
150   }
151
152   if( !mRotationTrigger )
153   {
154     mRotationTrigger = TriggerEventFactory::CreateTriggerEvent( MakeCallback( this, &WindowRenderSurface::ProcessRotationRequest ), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER );
155   }
156
157   mPositionSize.width = width;
158   mPositionSize.height = height;
159
160   mRotationAngle = angle;
161   mRotationFinished = false;
162
163   mWindowBase->SetWindowRotationAngle( mRotationAngle );
164
165   DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::Rotate: angle = %d screen rotation = %d\n", mRotationAngle, mScreenRotationAngle );
166 }
167
168 WindowBase* WindowRenderSurface::GetWindowBase()
169 {
170   return mWindowBase.get();
171 }
172
173 WindowBase::OutputSignalType& WindowRenderSurface::OutputTransformedSignal()
174 {
175   return mOutputTransformedSignal;
176 }
177
178 PositionSize WindowRenderSurface::GetPositionSize() const
179 {
180   return mPositionSize;
181 }
182
183 void WindowRenderSurface::GetDpi( unsigned int& dpiHorizontal, unsigned int& dpiVertical )
184 {
185   if( mDpiHorizontal == 0 || mDpiVertical == 0 )
186   {
187     const char* environmentDpiHorizontal = std::getenv( DALI_ENV_DPI_HORIZONTAL );
188     mDpiHorizontal = environmentDpiHorizontal ? std::atoi( environmentDpiHorizontal ) : 0;
189
190     const char* environmentDpiVertical = std::getenv( DALI_ENV_DPI_VERTICAL );
191     mDpiVertical = environmentDpiVertical ? std::atoi( environmentDpiVertical ) : 0;
192
193     if( mDpiHorizontal == 0 || mDpiVertical == 0 )
194     {
195       mWindowBase->GetDpi( mDpiHorizontal, mDpiVertical );
196     }
197   }
198
199   dpiHorizontal = mDpiHorizontal;
200   dpiVertical = mDpiVertical;
201 }
202
203 void WindowRenderSurface::InitializeGraphics()
204 {
205   mGraphics = &mAdaptor->GetGraphicsInterface();
206
207   DALI_ASSERT_ALWAYS( mGraphics && "Graphics interface is not created" );
208
209   auto eglGraphics = static_cast<EglGraphics *>(mGraphics);
210   mEGL = &eglGraphics->GetEglInterface();
211
212   if ( mEGLContext == NULL )
213   {
214     // Create the OpenGL context for this window
215     Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>(*mEGL);
216     eglImpl.ChooseConfig(true, mColorDepth);
217     eglImpl.CreateWindowContext( mEGLContext );
218
219     // Create the OpenGL surface
220     CreateSurface();
221   }
222 }
223
224 void WindowRenderSurface::CreateSurface()
225 {
226   DALI_LOG_TRACE_METHOD( gWindowRenderSurfaceLogFilter );
227
228   int width, height;
229   if( mScreenRotationAngle == 0 || mScreenRotationAngle == 180 )
230   {
231     width = mPositionSize.width;
232     height = mPositionSize.height;
233   }
234   else
235   {
236     width = mPositionSize.height;
237     height = mPositionSize.width;
238   }
239
240   // Create the EGL window
241   EGLNativeWindowType window = mWindowBase->CreateEglWindow( width, height );
242
243   auto eglGraphics = static_cast<EglGraphics *>(mGraphics);
244
245   Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
246   mEGLSurface = eglImpl.CreateSurfaceWindow( window, mColorDepth );
247
248   // Check rotation capability
249   mRotationSupported = mWindowBase->IsEglWindowRotationSupported();
250
251   DALI_LOG_RELEASE_INFO("WindowRenderSurface::CreateSurface: WinId (%d), w = %d h = %d angle = %d screen rotation = %d\n",
252       mWindowBase->GetNativeWindowId(), mPositionSize.width, mPositionSize.height, mRotationAngle, mScreenRotationAngle );
253 }
254
255 void WindowRenderSurface::DestroySurface()
256 {
257   DALI_LOG_TRACE_METHOD( gWindowRenderSurfaceLogFilter );
258
259   auto eglGraphics = static_cast<EglGraphics *>(mGraphics);
260   if( eglGraphics )
261   {
262     DALI_LOG_RELEASE_INFO("WindowRenderSurface::DestroySurface: WinId (%d)\n", mWindowBase->GetNativeWindowId() );
263
264     Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
265
266     eglImpl.DestroySurface( mEGLSurface );
267     mEGLSurface = nullptr;
268
269     // Destroy context also
270     eglImpl.DestroyContext( mEGLContext );
271     mEGLContext = nullptr;
272
273     mWindowBase->DestroyEglWindow();
274   }
275 }
276
277 bool WindowRenderSurface::ReplaceGraphicsSurface()
278 {
279   DALI_LOG_TRACE_METHOD( gWindowRenderSurfaceLogFilter );
280
281   // Destroy the old one
282   mWindowBase->DestroyEglWindow();
283
284   int width, height;
285   if( mScreenRotationAngle == 0 || mScreenRotationAngle == 180 )
286   {
287     width = mPositionSize.width;
288     height = mPositionSize.height;
289   }
290   else
291   {
292     width = mPositionSize.height;
293     height = mPositionSize.width;
294   }
295
296   // Create the EGL window
297   EGLNativeWindowType window = mWindowBase->CreateEglWindow( width, height );
298
299   // Set screen rotation
300   mScreenRotationFinished = false;
301
302   auto eglGraphics = static_cast<EglGraphics *>(mGraphics);
303
304   Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
305   return eglImpl.ReplaceSurfaceWindow( window, mEGLSurface, mEGLContext );
306 }
307
308 void WindowRenderSurface::MoveResize( Dali::PositionSize positionSize )
309 {
310   bool needToMove = false;
311   bool needToResize = false;
312
313   // Check moving
314   if( (fabs(positionSize.x - mPositionSize.x) > MINIMUM_DIMENSION_CHANGE) ||
315       (fabs(positionSize.y - mPositionSize.y) > MINIMUM_DIMENSION_CHANGE) )
316   {
317     needToMove = true;
318   }
319
320   // Check resizing
321   if( (fabs(positionSize.width - mPositionSize.width) > MINIMUM_DIMENSION_CHANGE) ||
322       (fabs(positionSize.height - mPositionSize.height) > MINIMUM_DIMENSION_CHANGE) )
323   {
324     needToResize = true;
325   }
326
327   if( needToResize )
328   {
329     if( needToMove )
330     {
331       mWindowBase->MoveResize( positionSize );
332     }
333     else
334     {
335       mWindowBase->Resize( positionSize );
336     }
337
338     mResizeFinished = false;
339     mPositionSize = positionSize;
340   }
341   else
342   {
343     if( needToMove )
344     {
345       mWindowBase->Move( positionSize );
346
347       mPositionSize = positionSize;
348     }
349   }
350
351   DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::MoveResize: %d, %d, %d, %d\n", mPositionSize.x, mPositionSize.y, mPositionSize.width, mPositionSize.height );
352 }
353
354 void WindowRenderSurface::StartRender()
355 {
356 }
357
358 bool WindowRenderSurface::PreRender( bool resizingSurface, const std::vector<Rect<int>>& damagedRects, Rect<int>& clippingRect )
359 {
360   Dali::Integration::Scene::FrameCallbackContainer callbacks;
361
362   Dali::Integration::Scene scene = mScene.GetHandle();
363   if( scene )
364   {
365     bool needFrameRenderedTrigger = false;
366
367     scene.GetFrameRenderedCallback( callbacks );
368     if( !callbacks.empty() )
369     {
370       int frameRenderedSync = mWindowBase->CreateFrameRenderedSyncFence();
371       if( frameRenderedSync != -1 )
372       {
373         Dali::Mutex::ScopedLock lock( mMutex );
374
375         DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PreRender: CreateFrameRenderedSyncFence [%d]\n", frameRenderedSync );
376
377         mFrameCallbackInfoContainer.push_back( std::unique_ptr< FrameCallbackInfo >( new FrameCallbackInfo( callbacks, frameRenderedSync ) ) );
378
379         needFrameRenderedTrigger = true;
380       }
381       else
382       {
383         DALI_LOG_ERROR( "WindowRenderSurface::PreRender: CreateFrameRenderedSyncFence is failed\n" );
384       }
385
386       // Clear callbacks
387       callbacks.clear();
388     }
389
390     scene.GetFramePresentedCallback( callbacks );
391     if( !callbacks.empty() )
392     {
393       int framePresentedSync = mWindowBase->CreateFramePresentedSyncFence();
394       if( framePresentedSync != -1 )
395       {
396         Dali::Mutex::ScopedLock lock( mMutex );
397
398         DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PreRender: CreateFramePresentedSyncFence [%d]\n", framePresentedSync );
399
400         mFrameCallbackInfoContainer.push_back( std::unique_ptr< FrameCallbackInfo >( new FrameCallbackInfo( callbacks, framePresentedSync ) ) );
401
402         needFrameRenderedTrigger = true;
403       }
404       else
405       {
406         DALI_LOG_ERROR( "WindowRenderSurface::PreRender: CreateFramePresentedSyncFence is failed\n" );
407       }
408
409       // Clear callbacks
410       callbacks.clear();
411     }
412
413     if( needFrameRenderedTrigger )
414     {
415       if( !mFrameRenderedTrigger )
416       {
417         mFrameRenderedTrigger = std::unique_ptr< TriggerEventInterface >( TriggerEventFactory::CreateTriggerEvent( MakeCallback( this, &WindowRenderSurface::ProcessFrameCallback ),
418                                                                                                                    TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER ) );
419       }
420       mFrameRenderedTrigger->Trigger();
421     }
422   }
423
424   MakeContextCurrent();
425
426   auto eglGraphics = static_cast<EglGraphics *>(mGraphics);
427
428   if( resizingSurface )
429   {
430     // Window rotate or screen rotate
431     if( !mRotationFinished || !mScreenRotationFinished )
432     {
433       int totalAngle = (mRotationAngle + mScreenRotationAngle) % 360;
434
435       mWindowBase->SetEglWindowRotation( totalAngle );
436       mWindowBase->SetEglWindowBufferTransform( totalAngle );
437
438       // Reset only screen rotation flag
439       mScreenRotationFinished = true;
440
441       DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PreRender: Set rotation [%d] [%d]\n", mRotationAngle, mScreenRotationAngle );
442     }
443
444     // Only window rotate
445     if( !mRotationFinished )
446     {
447       mWindowBase->SetEglWindowTransform( mRotationAngle );
448     }
449
450     // Resize case
451     if( !mResizeFinished )
452     {
453       mWindowBase->ResizeEglWindow( mPositionSize );
454       mResizeFinished = true;
455
456       DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PreRender: Set resize\n" );
457     }
458
459     if (eglGraphics)
460     {
461       Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
462       eglImpl.SetFullSwapNextFrame();
463     }
464   }
465
466   if (eglGraphics)
467   {
468     Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
469     eglImpl.SetDamage( mEGLSurface, damagedRects, clippingRect );
470   }
471
472   return true;
473 }
474
475 void WindowRenderSurface::PostRender( bool renderToFbo, bool replacingSurface, bool resizingSurface, const std::vector<Rect<int>>& damagedRects )
476 {
477   // Inform the gl implementation that rendering has finished before informing the surface
478   auto eglGraphics = static_cast<EglGraphics *>(mGraphics);
479   if ( eglGraphics )
480   {
481     GlImplementation& mGLES = eglGraphics->GetGlesInterface();
482     mGLES.PostRender();
483
484     if( renderToFbo )
485     {
486       mGLES.Flush();
487       mGLES.Finish();
488     }
489     else
490     {
491       if( resizingSurface )
492       {
493         if( !mRotationFinished )
494         {
495           if( mThreadSynchronization )
496           {
497             // Enable PostRender flag
498             mThreadSynchronization->PostRenderStarted();
499           }
500
501           DALI_LOG_RELEASE_INFO("WindowRenderSurface::PostRender: Trigger rotation event\n" );
502
503           mRotationTrigger->Trigger();
504
505           if( mThreadSynchronization )
506           {
507             // Wait until the event-thread complete the rotation event processing
508             mThreadSynchronization->PostRenderWaitForCompletion();
509           }
510         }
511       }
512     }
513
514     Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
515     eglImpl.SwapBuffers( mEGLSurface, damagedRects );
516
517     if( mRenderNotification )
518     {
519       mRenderNotification->Trigger();
520     }
521   }
522 }
523
524 void WindowRenderSurface::StopRender()
525 {
526 }
527
528 void WindowRenderSurface::SetThreadSynchronization( ThreadSynchronizationInterface& threadSynchronization )
529 {
530   DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::SetThreadSynchronization: called\n" );
531
532   mThreadSynchronization = &threadSynchronization;
533 }
534
535 void WindowRenderSurface::ReleaseLock()
536 {
537   // Nothing to do.
538 }
539
540 Dali::RenderSurfaceInterface::Type WindowRenderSurface::GetSurfaceType()
541 {
542   return Dali::RenderSurfaceInterface::WINDOW_RENDER_SURFACE;
543 }
544
545 void WindowRenderSurface::MakeContextCurrent()
546 {
547   if ( mEGL != nullptr )
548   {
549     mEGL->MakeContextCurrent( mEGLSurface, mEGLContext );
550   }
551 }
552
553 Integration::DepthBufferAvailable WindowRenderSurface::GetDepthBufferRequired()
554 {
555   return mGraphics ? mGraphics->GetDepthBufferRequired() : Integration::DepthBufferAvailable::FALSE;
556 }
557
558 Integration::StencilBufferAvailable WindowRenderSurface::GetStencilBufferRequired()
559 {
560   return mGraphics ? mGraphics->GetStencilBufferRequired() : Integration::StencilBufferAvailable::FALSE;
561 }
562
563 void WindowRenderSurface::OutputTransformed()
564 {
565   int screenRotationAngle = mWindowBase->GetScreenRotationAngle();
566
567   if( mScreenRotationAngle != screenRotationAngle )
568   {
569     mScreenRotationAngle = screenRotationAngle;
570     mScreenRotationFinished = false;
571
572     mOutputTransformedSignal.Emit();
573
574     DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::OutputTransformed: angle = %d screen rotation = %d\n", mRotationAngle, mScreenRotationAngle );
575   }
576   else
577   {
578     DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::OutputTransformed: Ignore output transform [%d]\n", mScreenRotationAngle );
579   }
580 }
581
582 void WindowRenderSurface::ProcessRotationRequest()
583 {
584   mRotationFinished = true;
585
586   mWindowBase->WindowRotationCompleted( mRotationAngle, mPositionSize.width, mPositionSize.height );
587
588   DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::ProcessRotationRequest: Rotation Done\n" );
589
590   if( mThreadSynchronization )
591   {
592     mThreadSynchronization->PostRenderComplete();
593   }
594 }
595
596 void WindowRenderSurface::ProcessFrameCallback()
597 {
598   Dali::Mutex::ScopedLock lock( mMutex );
599
600   for( auto&& iter : mFrameCallbackInfoContainer )
601   {
602     if( !iter->fileDescriptorMonitor )
603     {
604       iter->fileDescriptorMonitor = std::unique_ptr< FileDescriptorMonitor >( new FileDescriptorMonitor( iter->fileDescriptor,
605                                                                              MakeCallback( this, &WindowRenderSurface::OnFileDescriptorEventDispatched ), FileDescriptorMonitor::FD_READABLE ) );
606
607       DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::ProcessFrameCallback: Add handler [%d]\n", iter->fileDescriptor );
608     }
609   }
610 }
611
612 void WindowRenderSurface::OnFileDescriptorEventDispatched( FileDescriptorMonitor::EventType eventBitMask, int fileDescriptor )
613 {
614   if( !( eventBitMask & FileDescriptorMonitor::FD_READABLE ) )
615   {
616     DALI_LOG_ERROR( "WindowRenderSurface::OnFileDescriptorEventDispatched: file descriptor error [%d]\n", eventBitMask );
617     close( fileDescriptor );
618     return;
619   }
620
621   DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::OnFileDescriptorEventDispatched: Frame rendered [%d]\n", fileDescriptor );
622
623   std::unique_ptr< FrameCallbackInfo > callbackInfo;
624   {
625     Dali::Mutex::ScopedLock lock( mMutex );
626     auto frameCallbackInfo = std::find_if( mFrameCallbackInfoContainer.begin(), mFrameCallbackInfoContainer.end(),
627                                       [fileDescriptor]( std::unique_ptr< FrameCallbackInfo >& callbackInfo )
628                                       {
629                                         return callbackInfo->fileDescriptor == fileDescriptor;
630                                       } );
631     if( frameCallbackInfo != mFrameCallbackInfoContainer.end() )
632     {
633       callbackInfo = std::move( *frameCallbackInfo );
634
635       mFrameCallbackInfoContainer.erase( frameCallbackInfo );
636     }
637   }
638
639   // Call the connected callback
640   if( callbackInfo )
641   {
642     for( auto&& iter : ( callbackInfo )->callbacks )
643     {
644       CallbackBase::Execute( *( iter.first ), iter.second );
645     }
646   }
647 }
648
649 } // namespace Adaptor
650
651 } // namespace internal
652
653 } // namespace Dali