[3.0] Fix build error
[platform/core/uifw/dali-adaptor.git] / adaptors / ecore / wayland / window-render-surface-ecore-wl.cpp
1 /*
2  * Copyright (c) 2017 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 <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 <wl-types.h>
27 #include <gl/egl-implementation.h>
28 #include <adaptors/common/adaptor-impl.h>
29 #include <integration-api/trigger-event-factory-interface.h>
30
31 namespace Dali
32 {
33
34 #if defined(DEBUG_ENABLED)
35 extern Debug::Filter* gRenderSurfaceLogFilter;
36 #endif
37
38 namespace ECore
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 } // unnamed namespace
47
48 WindowRenderSurface::WindowRenderSurface( Dali::PositionSize positionSize,
49                                           Any surface,
50                                           const std::string& name,
51                                           bool isTransparent)
52 : EcoreWlRenderSurface( positionSize, surface, name, isTransparent ),
53   mWlWindow( NULL ),
54   mWlSurface( NULL ),
55   mEglWindow( NULL ),
56   mThreadSynchronization( NULL ),
57   mRotationTrigger( NULL ),
58   mRotationAngle( 0 ),
59   mScreenRotationAngle( 0 ),
60   mRotationSupported( false ),
61   mRotationFinished( true ),
62   mScreenRotationFinished( true )
63 {
64   DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "Creating Window\n" );
65   Init( surface );
66 }
67
68 WindowRenderSurface::~WindowRenderSurface()
69 {
70   if( mEglWindow != NULL )
71   {
72     wl_egl_window_destroy(mEglWindow);
73     mEglWindow = NULL;
74   }
75
76   if( mOwnSurface )
77   {
78     ecore_wl_window_free( mWlWindow );
79   }
80
81   if( mRotationTrigger )
82   {
83     delete mRotationTrigger;
84   }
85
86 }
87
88 Ecore_Wl_Window* WindowRenderSurface::GetDrawable()
89 {
90   // already an e-core type
91   return mWlWindow;
92 }
93
94 Any WindowRenderSurface::GetSurface()
95 {
96   // already an e-core type
97   return Any( mWlWindow );
98 }
99
100 Ecore_Wl_Window* WindowRenderSurface::GetWlWindow()
101 {
102   return mWlWindow;
103 }
104
105 void WindowRenderSurface::RequestRotation( int angle, int width, int height )
106 {
107   if( !mRotationSupported )
108   {
109     DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::Rotate: Rotation is not supported!\n" );
110     return;
111   }
112
113   if( !mRotationTrigger )
114   {
115     TriggerEventFactoryInterface& triggerFactory = Internal::Adaptor::Adaptor::GetImplementation( Adaptor::Get() ).GetTriggerEventFactoryInterface();
116     mRotationTrigger = triggerFactory.CreateTriggerEvent( MakeCallback( this, &WindowRenderSurface::ProcessRotationRequest ), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER );
117   }
118
119   mPositionSize.width = width;
120   mPositionSize.height = height;
121
122   mRotationAngle = angle;
123   mRotationFinished = false;
124
125   ecore_wl_window_rotation_set( mWlWindow, mRotationAngle );
126
127   DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::Rotate: angle = %d screen rotation = %d\n", mRotationAngle, mScreenRotationAngle );
128 }
129
130 void WindowRenderSurface::OutputTransformed()
131 {
132   int transform;
133
134   if( ecore_wl_window_ignore_output_transform_get( mWlWindow ) )
135   {
136     transform = 0;
137   }
138   else
139   {
140     transform = ecore_wl_output_transform_get( ecore_wl_window_output_find( mWlWindow ) );
141   }
142
143   mScreenRotationAngle = transform * 90;
144   mScreenRotationFinished = false;
145
146   DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::OutputTransformed: angle = %d screen rotation = %d\n", mRotationAngle, mScreenRotationAngle );
147 }
148
149 void WindowRenderSurface::InitializeEgl( EglInterface& eglIf )
150 {
151   DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
152
153   Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( eglIf );
154
155   eglImpl.ChooseConfig(true, mColorDepth);
156 }
157
158 void WindowRenderSurface::CreateEglSurface( EglInterface& eglIf )
159 {
160   DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
161
162   Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( eglIf );
163
164   // create the EGL window
165   if( mScreenRotationAngle == 0 || mScreenRotationAngle == 180 )
166   {
167     mEglWindow = wl_egl_window_create( mWlSurface, mPositionSize.width, mPositionSize.height );
168   }
169   else
170   {
171     mEglWindow = wl_egl_window_create( mWlSurface, mPositionSize.height, mPositionSize.width );
172   }
173
174   EGLNativeWindowType windowType( mEglWindow );
175   eglImpl.CreateSurfaceWindow( windowType, mColorDepth );
176
177 #ifdef SCREEN_ROTATION_ENABLED
178   // Check capability
179   wl_egl_window_capability capability = static_cast< wl_egl_window_capability >( wl_egl_window_get_capabilities( mEglWindow ) );
180   if( capability == WL_EGL_WINDOW_CAPABILITY_ROTATION_SUPPORTED )
181   {
182     DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::CreateEglSurface: capability = %d\n", capability );
183     mRotationSupported = true;
184   }
185
186   DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::CreateEglSurface: w = %d h = %d angle = %d screen rotation = %d\n", mPositionSize.width, mPositionSize.height, mRotationAngle, mScreenRotationAngle );
187 #endif
188 }
189
190 void WindowRenderSurface::DestroyEglSurface( EglInterface& eglIf )
191 {
192   DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
193
194   Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( eglIf );
195   eglImpl.DestroySurface();
196
197   if( mEglWindow != NULL )
198   {
199     wl_egl_window_destroy(mEglWindow);
200     mEglWindow = NULL;
201   }
202 }
203
204 bool WindowRenderSurface::ReplaceEGLSurface( EglInterface& egl )
205 {
206   DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
207
208   if( mEglWindow != NULL )
209   {
210     wl_egl_window_destroy(mEglWindow);
211     mEglWindow = NULL;
212   }
213
214   if( mScreenRotationAngle == 0 || mScreenRotationAngle == 180 )
215   {
216     mEglWindow = wl_egl_window_create( mWlSurface, mPositionSize.width, mPositionSize.height );
217   }
218   else
219   {
220     mEglWindow = wl_egl_window_create( mWlSurface, mPositionSize.height, mPositionSize.width );
221   }
222
223   // Set screen rotation
224   mScreenRotationFinished = false;
225
226   Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
227   EGLNativeWindowType windowType( mEglWindow );
228   return eglImpl.ReplaceSurfaceWindow( windowType );
229 }
230
231 void WindowRenderSurface::MoveResize( Dali::PositionSize positionSize )
232 {
233   bool needToMove = false;
234   bool needToResize = false;
235
236   // check moving
237   if( (fabs(positionSize.x - mPositionSize.x) > MINIMUM_DIMENSION_CHANGE) ||
238       (fabs(positionSize.y - mPositionSize.y) > MINIMUM_DIMENSION_CHANGE) )
239   {
240     needToMove = true;
241   }
242
243   // check resizing
244   if( (fabs(positionSize.width - mPositionSize.width) > MINIMUM_DIMENSION_CHANGE) ||
245       (fabs(positionSize.height - mPositionSize.height) > MINIMUM_DIMENSION_CHANGE) )
246   {
247     needToResize = true;
248   }
249
250   if(needToMove)
251   {
252     ecore_wl_window_move(mWlWindow, positionSize.x, positionSize.y);
253     mPositionSize = positionSize;
254   }
255   if (needToResize)
256   {
257     ecore_wl_window_resize(mWlWindow, positionSize.width, positionSize.height, 0);
258     mPositionSize = positionSize;
259   }
260
261 }
262
263 void WindowRenderSurface::Map()
264 {
265   ecore_wl_window_show(mWlWindow);
266 }
267
268 void WindowRenderSurface::StartRender()
269 {
270 }
271
272 bool WindowRenderSurface::PreRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, bool resizingSurface )
273 {
274 #ifdef SCREEN_ROTATION_ENABLED
275   if( resizingSurface )
276   {
277     // Window rotate or screen rotate
278     if( !mRotationFinished || !mScreenRotationFinished )
279     {
280       wl_egl_window_rotation rotation;
281       wl_output_transform bufferTransform;
282       int totalAngle = (mRotationAngle + mScreenRotationAngle) % 360;
283
284       switch( totalAngle )
285       {
286         case 0:
287         {
288           rotation = ROTATION_0;
289           bufferTransform = WL_OUTPUT_TRANSFORM_NORMAL;
290           break;
291         }
292         case 90:
293         {
294           rotation = ROTATION_270;
295           bufferTransform = WL_OUTPUT_TRANSFORM_90;
296           break;
297         }
298         case 180:
299         {
300           rotation = ROTATION_180;
301           bufferTransform = WL_OUTPUT_TRANSFORM_180;
302           break;
303         }
304         case 270:
305         {
306           rotation = ROTATION_90;
307           bufferTransform = WL_OUTPUT_TRANSFORM_270;
308           break;
309         }
310         default:
311         {
312           rotation = ROTATION_0;
313           bufferTransform = WL_OUTPUT_TRANSFORM_NORMAL;
314           break;
315         }
316       }
317
318       wl_egl_window_set_rotation( mEglWindow, rotation );
319
320       wl_egl_window_set_buffer_transform( mEglWindow, bufferTransform );
321
322       // Reset only screen rotation flag
323       mScreenRotationFinished = true;
324
325       DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PreRender: Set rotation [%d] [%d]\n", mRotationAngle, mScreenRotationAngle );
326     }
327
328     // Only window rotate
329     if( !mRotationFinished )
330     {
331       wl_output_transform windowTransform;
332
333       switch( mRotationAngle )
334       {
335         case 0:
336         {
337           windowTransform = WL_OUTPUT_TRANSFORM_NORMAL;
338           break;
339         }
340         case 90:
341         {
342           windowTransform = WL_OUTPUT_TRANSFORM_90;
343           break;
344         }
345         case 180:
346         {
347           windowTransform = WL_OUTPUT_TRANSFORM_180;
348           break;
349         }
350         case 270:
351         {
352           windowTransform = WL_OUTPUT_TRANSFORM_270;
353           break;
354         }
355         default:
356         {
357           windowTransform = WL_OUTPUT_TRANSFORM_NORMAL;
358           break;
359         }
360       }
361
362       wl_egl_window_set_window_transform( mEglWindow, windowTransform );
363     }
364   }
365 #endif
366
367   return true;
368 }
369
370 void WindowRenderSurface::PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, DisplayConnection* displayConnection, bool replacingSurface, bool resizingSurface )
371 {
372 #ifdef SCREEN_ROTATION_ENABLED
373   if( resizingSurface )
374   {
375     if( !mRotationFinished )
376     {
377       DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PostRender: Trigger rotation event\n" );
378
379       mRotationTrigger->Trigger();
380
381       if( mThreadSynchronization )
382       {
383         // Wait until the event-thread complete the rotation event processing
384         mThreadSynchronization->PostRenderWaitForCompletion();
385       }
386     }
387   }
388 #endif
389
390   Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
391   eglImpl.SwapBuffers();
392
393   if( mRenderNotification )
394   {
395     mRenderNotification->Trigger();
396   }
397 }
398
399 void WindowRenderSurface::StopRender()
400 {
401 }
402
403 void WindowRenderSurface::SetViewMode( ViewMode viewMode )
404 {
405   //FIXME
406 }
407
408 void WindowRenderSurface::CreateWlRenderable()
409 {
410    // if width or height are zero, go full screen.
411   if ( (mPositionSize.width == 0) || (mPositionSize.height == 0) )
412   {
413     // Default window size == screen size
414     mPositionSize.x = 0;
415     mPositionSize.y = 0;
416
417     ecore_wl_screen_size_get( &mPositionSize.width, &mPositionSize.height );
418   }
419
420   mWlWindow = ecore_wl_window_new( 0, mPositionSize.x, mPositionSize.y, mPositionSize.width, mPositionSize.height, ECORE_WL_WINDOW_BUFFER_TYPE_EGL_WINDOW );
421
422   if ( mWlWindow == 0 )
423   {
424     DALI_ASSERT_ALWAYS(0 && "Failed to create Wayland window");
425   }
426
427   mWlSurface = ecore_wl_window_surface_create( mWlWindow );
428
429   if( mColorDepth == COLOR_DEPTH_32 )
430   {
431     ecore_wl_window_alpha_set( mWlWindow, true );
432   }
433   else
434   {
435     ecore_wl_window_alpha_set( mWlWindow, false );
436   }
437
438   // Get output transform
439   if( !ecore_wl_window_ignore_output_transform_get( mWlWindow ) )
440   {
441     Ecore_Wl_Output* output = ecore_wl_window_output_find( mWlWindow );
442
443     int transform = ecore_wl_output_transform_get( output );
444
445     mScreenRotationAngle = transform * 90;
446     mScreenRotationFinished = false;
447   }
448 }
449
450 void WindowRenderSurface::UseExistingRenderable( unsigned int surfaceId )
451 {
452   mWlWindow = AnyCast< Ecore_Wl_Window* >( surfaceId );
453 }
454
455 void WindowRenderSurface::SetThreadSynchronization( ThreadSynchronizationInterface& threadSynchronization )
456 {
457   DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::SetThreadSynchronization: called\n" );
458
459   mThreadSynchronization = &threadSynchronization;
460 }
461
462 void WindowRenderSurface::ReleaseLock()
463 {
464   // Nothing to do.
465 }
466
467 void WindowRenderSurface::ProcessRotationRequest()
468 {
469 #ifdef SCREEN_ROTATION_ENABLED
470   mRotationFinished = true;
471
472   ecore_wl_window_rotation_change_done_send( mWlWindow );
473
474   DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::ProcessRotationRequest: Rotation Done\n" );
475
476   if( mThreadSynchronization )
477   {
478     mThreadSynchronization->PostRenderComplete();
479   }
480 #endif
481 }
482
483 } // namespace ECore
484
485 } // namespace Dali