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