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