WindowRenderSurface and EventHandler refactoring
[platform/core/uifw/dali-adaptor.git] / dali / internal / window-system / common / window-render-surface.cpp
1 /*
2  * Copyright (c) 2018 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/trigger-event-factory-interface.h>
27 #include <dali/integration-api/thread-synchronization-interface.h>
28 #include <dali/internal/graphics/gles20/egl-implementation.h>
29 #include <dali/internal/adaptor/common/adaptor-impl.h>
30 #include <dali/internal/window-system/common/window-base.h>
31 #include <dali/internal/window-system/common/window-factory.h>
32 #include <dali/internal/window-system/common/window-system.h>
33
34 namespace Dali
35 {
36 namespace Internal
37 {
38 namespace Adaptor
39 {
40
41 namespace
42 {
43
44 const int MINIMUM_DIMENSION_CHANGE( 1 ); ///< Minimum change for window to be considered to have moved
45
46 #if defined(DEBUG_ENABLED)
47 Debug::Filter* gWindowRenderSurfaceLogFilter = Debug::Filter::New(Debug::Verbose, false, "LOG_WINDOW_RENDER_SURFACE");
48 #endif
49
50 } // unnamed namespace
51
52 WindowRenderSurface::WindowRenderSurface( Dali::PositionSize positionSize, Any surface, bool isTransparent )
53 : mPositionSize( positionSize ),
54   mWindowBase(),
55   mThreadSynchronization( NULL ),
56   mRenderNotification( NULL ),
57   mRotationTrigger( NULL ),
58   mColorDepth( isTransparent ? COLOR_DEPTH_32 : COLOR_DEPTH_24 ),
59   mRotationAngle( 0 ),
60   mScreenRotationAngle( 0 ),
61   mOwnSurface( false ),
62   mRotationSupported( false ),
63   mRotationFinished( true ),
64   mScreenRotationFinished( true ),
65   mResizeFinished( true )
66 {
67   DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "Creating Window\n" );
68   Initialize( surface );
69 }
70
71 WindowRenderSurface::~WindowRenderSurface()
72 {
73   if( mRotationTrigger )
74   {
75     delete mRotationTrigger;
76   }
77 }
78
79 void WindowRenderSurface::Initialize( Any surface )
80 {
81   // if width or height are zero, go full screen.
82  if ( (mPositionSize.width == 0) || (mPositionSize.height == 0) )
83  {
84    // Default window size == screen size
85    mPositionSize.x = 0;
86    mPositionSize.y = 0;
87
88    WindowSystem::GetScreenSize( mPositionSize.width, mPositionSize.height );
89  }
90
91   // Create a window base
92   auto windowFactory = Dali::Internal::Adaptor::GetWindowFactory();
93   mWindowBase = windowFactory->CreateWindowBase( mPositionSize, surface, ( mColorDepth == COLOR_DEPTH_32 ? true : false ) );
94
95   // Connect signals
96   mWindowBase->OutputTransformedSignal().Connect( this, &WindowRenderSurface::OutputTransformed );
97
98   // Check screen rotation
99   mScreenRotationAngle = mWindowBase->GetScreenRotationAngle();
100   if( mScreenRotationAngle != 0 )
101   {
102     mScreenRotationFinished = false;
103   }
104 }
105
106 Any WindowRenderSurface::GetNativeWindow()
107 {
108   return mWindowBase->GetNativeWindow();
109 }
110
111 int WindowRenderSurface::GetNativeWindowId()
112 {
113   return mWindowBase->GetNativeWindowId();
114 }
115
116 void WindowRenderSurface::Map()
117 {
118   mWindowBase->Show();
119 }
120
121 void WindowRenderSurface::SetRenderNotification( TriggerEventInterface* renderNotification )
122 {
123   mRenderNotification = renderNotification;
124 }
125
126 void WindowRenderSurface::SetTransparency( bool transparent )
127 {
128   mWindowBase->SetTransparency( transparent );
129 }
130
131 void WindowRenderSurface::RequestRotation( int angle, int width, int height )
132 {
133   if( !mRotationSupported )
134   {
135     DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::Rotate: Rotation is not supported!\n" );
136     return;
137   }
138
139   if( !mRotationTrigger )
140   {
141     TriggerEventFactoryInterface& triggerFactory = Internal::Adaptor::Adaptor::GetImplementation( Adaptor::Get() ).GetTriggerEventFactoryInterface();
142     mRotationTrigger = triggerFactory.CreateTriggerEvent( MakeCallback( this, &WindowRenderSurface::ProcessRotationRequest ), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER );
143   }
144
145   mPositionSize.width = width;
146   mPositionSize.height = height;
147
148   mRotationAngle = angle;
149   mRotationFinished = false;
150
151   mWindowBase->SetWindowRotationAngle( mRotationAngle );
152
153   DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::Rotate: angle = %d screen rotation = %d\n", mRotationAngle, mScreenRotationAngle );
154 }
155
156 WindowBase* WindowRenderSurface::GetWindowBase()
157 {
158   return mWindowBase.get();
159 }
160
161 PositionSize WindowRenderSurface::GetPositionSize() const
162 {
163   return mPositionSize;
164 }
165
166 void WindowRenderSurface::GetDpi( unsigned int& dpiHorizontal, unsigned int& dpiVertical )
167 {
168   mWindowBase->GetDpi( dpiHorizontal, dpiVertical );
169 }
170
171 void WindowRenderSurface::InitializeEgl( EglInterface& eglIf )
172 {
173   DALI_LOG_TRACE_METHOD( gWindowRenderSurfaceLogFilter );
174
175   Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( eglIf );
176
177   eglImpl.ChooseConfig(true, mColorDepth);
178 }
179
180 void WindowRenderSurface::CreateEglSurface( EglInterface& eglIf )
181 {
182   DALI_LOG_TRACE_METHOD( gWindowRenderSurfaceLogFilter );
183
184   int width, height;
185   if( mScreenRotationAngle == 0 || mScreenRotationAngle == 180 )
186   {
187     width = mPositionSize.width;
188     height = mPositionSize.height;
189   }
190   else
191   {
192     width = mPositionSize.height;
193     height = mPositionSize.width;
194   }
195
196   // create the EGL window
197   EGLNativeWindowType window = mWindowBase->CreateEglWindow( width, height );
198
199   Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( eglIf );
200   eglImpl.CreateSurfaceWindow( window, mColorDepth );
201
202   // Check rotation capability
203   mRotationSupported = mWindowBase->IsEglWindowRotationSupported();
204
205   DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::CreateEglSurface: w = %d h = %d angle = %d screen rotation = %d\n", mPositionSize.width, mPositionSize.height, mRotationAngle, mScreenRotationAngle );
206 }
207
208 void WindowRenderSurface::DestroyEglSurface( EglInterface& eglIf )
209 {
210   DALI_LOG_TRACE_METHOD( gWindowRenderSurfaceLogFilter );
211
212   Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( eglIf );
213   eglImpl.DestroySurface();
214
215   mWindowBase->DestroyEglWindow();
216 }
217
218 bool WindowRenderSurface::ReplaceEGLSurface( EglInterface& egl )
219 {
220   DALI_LOG_TRACE_METHOD( gWindowRenderSurfaceLogFilter );
221
222   // Destroy the old one
223   mWindowBase->DestroyEglWindow();
224
225   int width, height;
226   if( mScreenRotationAngle == 0 || mScreenRotationAngle == 180 )
227   {
228     width = mPositionSize.width;
229     height = mPositionSize.height;
230   }
231   else
232   {
233     width = mPositionSize.height;
234     height = mPositionSize.width;
235   }
236
237   // create the EGL window
238   EGLNativeWindowType window = mWindowBase->CreateEglWindow( width, height );
239
240   // Set screen rotation
241   mScreenRotationFinished = false;
242
243   Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
244   return eglImpl.ReplaceSurfaceWindow( window );
245 }
246
247 void WindowRenderSurface::MoveResize( Dali::PositionSize positionSize )
248 {
249   bool needToMove = false;
250   bool needToResize = false;
251
252   // check moving
253   if( (fabs(positionSize.x - mPositionSize.x) > MINIMUM_DIMENSION_CHANGE) ||
254       (fabs(positionSize.y - mPositionSize.y) > MINIMUM_DIMENSION_CHANGE) )
255   {
256     needToMove = true;
257   }
258
259   // check resizing
260   if( (fabs(positionSize.width - mPositionSize.width) > MINIMUM_DIMENSION_CHANGE) ||
261       (fabs(positionSize.height - mPositionSize.height) > MINIMUM_DIMENSION_CHANGE) )
262   {
263     needToResize = true;
264   }
265
266   if( needToResize )
267   {
268     if( needToMove )
269     {
270       mWindowBase->MoveResize( positionSize );
271     }
272     else
273     {
274       mWindowBase->Resize( positionSize );
275     }
276
277     mResizeFinished = false;
278     mPositionSize = positionSize;
279   }
280   else
281   {
282     if( needToMove )
283     {
284       mWindowBase->Move( positionSize );
285
286       mPositionSize = positionSize;
287     }
288   }
289
290   DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::MoveResize: %d, %d, %d, %d\n", mPositionSize.x, mPositionSize.y, mPositionSize.width, mPositionSize.height );
291 }
292
293 void WindowRenderSurface::SetViewMode( ViewMode viewMode )
294 {
295   mWindowBase->SetViewMode( viewMode );
296 }
297
298 void WindowRenderSurface::StartRender()
299 {
300 }
301
302 bool WindowRenderSurface::PreRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, bool resizingSurface )
303 {
304   if( resizingSurface )
305   {
306 #ifdef OVER_TIZEN_VERSION_4
307     // Window rotate or screen rotate
308     if( !mRotationFinished || !mScreenRotationFinished )
309     {
310       int totalAngle = (mRotationAngle + mScreenRotationAngle) % 360;
311
312       mWindowBase->SetEglWindowRotation( totalAngle );
313       mWindowBase->SetEglWindowBufferTransform( totalAngle );
314
315       // Reset only screen rotation flag
316       mScreenRotationFinished = true;
317
318       DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PreRender: Set rotation [%d] [%d]\n", mRotationAngle, mScreenRotationAngle );
319     }
320
321     // Only window rotate
322     if( !mRotationFinished )
323     {
324       mWindowBase->SetEglWindowTransform( mRotationAngle );
325     }
326 #endif
327
328     // Resize case
329     if( !mResizeFinished )
330     {
331       mWindowBase->ResizeEglWindow( mPositionSize );
332       mResizeFinished = true;
333
334       DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PreRender: Set resize\n" );
335     }
336   }
337
338   return true;
339 }
340
341 void WindowRenderSurface::PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, Dali::DisplayConnection* displayConnection, bool replacingSurface, bool resizingSurface )
342 {
343   if( resizingSurface )
344   {
345     if( !mRotationFinished )
346     {
347       DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PostRender: Trigger rotation event\n" );
348
349       mRotationTrigger->Trigger();
350
351       if( mThreadSynchronization )
352       {
353         // Wait until the event-thread complete the rotation event processing
354         mThreadSynchronization->PostRenderWaitForCompletion();
355       }
356     }
357   }
358
359   Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
360   eglImpl.SwapBuffers();
361
362   if( mRenderNotification )
363   {
364     mRenderNotification->Trigger();
365   }
366 }
367
368 void WindowRenderSurface::StopRender()
369 {
370 }
371
372 void WindowRenderSurface::SetThreadSynchronization( ThreadSynchronizationInterface& threadSynchronization )
373 {
374   DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::SetThreadSynchronization: called\n" );
375
376   mThreadSynchronization = &threadSynchronization;
377 }
378
379 void WindowRenderSurface::ReleaseLock()
380 {
381   // Nothing to do.
382 }
383
384 RenderSurface::Type WindowRenderSurface::GetSurfaceType()
385 {
386   return RenderSurface::WINDOW_RENDER_SURFACE;
387 }
388
389 void WindowRenderSurface::OutputTransformed()
390 {
391   mScreenRotationAngle = mWindowBase->GetScreenRotationAngle();
392   mScreenRotationFinished = false;
393
394   DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::OutputTransformed: angle = %d screen rotation = %d\n", mRotationAngle, mScreenRotationAngle );
395 }
396
397 void WindowRenderSurface::ProcessRotationRequest()
398 {
399   mRotationFinished = true;
400
401   mWindowBase->WindowRotationCompleted( mRotationAngle, mPositionSize.width, mPositionSize.height );
402
403   DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::ProcessRotationRequest: Rotation Done\n" );
404
405   if( mThreadSynchronization )
406   {
407     mThreadSynchronization->PostRenderComplete();
408   }
409 }
410
411 } // namespace Adaptor
412
413 } // namespace internal
414
415 } // namespace Dali