Merge "Ol_chiki and Baybayin scripts added" into devel/master
[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 #include <dali/integration-api/gl-defines.h>
25
26 // INTERNAL INCLUDES
27 #include <wl-types.h>
28 #include <gl/egl-implementation.h>
29 #include <base/display-connection.h>
30 #include <adaptors/common/adaptor-impl.h>
31 #include <integration-api/trigger-event-factory-interface.h>
32
33 namespace Dali
34 {
35
36 #if defined(DEBUG_ENABLED)
37 extern Debug::Filter* gRenderSurfaceLogFilter;
38 #endif
39
40 namespace ECore
41 {
42
43 namespace
44 {
45
46 const int MINIMUM_DIMENSION_CHANGE( 1 ); ///< Minimum change for window to be considered to have moved
47
48 } // unnamed namespace
49
50 WindowRenderSurface::WindowRenderSurface( Dali::PositionSize positionSize,
51                                           Any surface,
52                                           const std::string& name,
53                                           bool isTransparent)
54 : EcoreWlRenderSurface( positionSize, surface, name, isTransparent ),
55   mWlWindow( NULL ),
56   mEglWindow( NULL ),
57   mThreadSynchronization( NULL ),
58   mRotationTrigger( NULL ),
59   mRotationSupported( false ),
60   mRotated( false )
61 {
62   DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "Creating Window\n" );
63   Init( surface );
64 }
65
66 WindowRenderSurface::~WindowRenderSurface()
67 {
68   if( mEglWindow != NULL )
69   {
70     wl_egl_window_destroy(mEglWindow);
71     mEglWindow = NULL;
72   }
73
74   if( mOwnSurface )
75   {
76     ecore_wl_window_free( mWlWindow );
77   }
78
79   if( mRotationTrigger )
80   {
81     delete mRotationTrigger;
82   }
83 }
84
85 Ecore_Wl_Window* WindowRenderSurface::GetDrawable()
86 {
87   // already an e-core type
88   return mWlWindow;
89 }
90
91 Any WindowRenderSurface::GetSurface()
92 {
93   // already an e-core type
94   return Any( mWlWindow );
95 }
96
97 Ecore_Wl_Window* WindowRenderSurface::GetWlWindow()
98 {
99   return mWlWindow;
100 }
101
102 void WindowRenderSurface::RequestRotation( Dali::Window::WindowOrientation orientation, int width, int height )
103 {
104   if( !mRotationSupported )
105   {
106     DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::Rotate: Rotation is not supported!\n" );
107     return;
108   }
109
110   DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::Rotate: orientation = %d\n", orientation );
111
112   if( !mRotationTrigger )
113   {
114     TriggerEventFactoryInterface& triggerFactory = Internal::Adaptor::Adaptor::GetImplementation( Adaptor::Get() ).GetTriggerEventFactoryInterface();
115     mRotationTrigger = triggerFactory.CreateTriggerEvent( MakeCallback( this, &WindowRenderSurface::ProcessRotationRequest ), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER );
116   }
117
118   mPosition.width = width;
119   mPosition.height = height;
120
121   mRotated = true;
122
123   int angle;
124   wl_egl_window_rotation rotation;
125
126   switch( orientation )
127   {
128     case Dali::Window::PORTRAIT:
129     {
130       angle = 0;
131       rotation = ROTATION_0;
132       break;
133     }
134     case Dali::Window::LANDSCAPE:
135     {
136       angle = 90;
137       rotation = ROTATION_270;
138       break;
139     }
140     case Dali::Window::PORTRAIT_INVERSE:
141     {
142       angle = 180;
143       rotation = ROTATION_180;
144       break;
145     }
146     case Dali::Window::LANDSCAPE_INVERSE:
147     {
148       angle = 270;
149       rotation = ROTATION_90;
150       break;
151     }
152     default:
153     {
154       angle = 0;
155       rotation = ROTATION_0;
156       break;
157     }
158   }
159
160   ecore_wl_window_rotation_set( mWlWindow, angle );
161
162   wl_egl_window_set_rotation( mEglWindow, rotation );
163 }
164
165 void WindowRenderSurface::InitializeEgl( EglInterface& eglIf )
166 {
167   DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
168
169   Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( eglIf );
170
171   eglImpl.ChooseConfig(true, mColorDepth);
172 }
173
174 void WindowRenderSurface::CreateEglSurface( EglInterface& eglIf )
175 {
176   DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
177
178   Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( eglIf );
179
180   // Temporary code for opaque window. We have to modify it after wayland team finish the work.
181   if( mColorDepth == COLOR_DEPTH_32 )
182   {
183     ecore_wl_window_alpha_set( mWlWindow, true );
184   }
185   else
186   {
187     ecore_wl_window_alpha_set( mWlWindow, false );
188   }
189
190   // create the EGL surface
191   ecore_wl_window_surface_create(mWlWindow);
192   mEglWindow = wl_egl_window_create(ecore_wl_window_surface_get(mWlWindow), mPosition.width, mPosition.height);
193   EGLNativeWindowType windowType( mEglWindow );
194   eglImpl.CreateSurfaceWindow( windowType, mColorDepth );
195
196   // Check capability
197   wl_egl_window_capability capability = static_cast< wl_egl_window_capability >( wl_egl_window_get_capabilities( mEglWindow ) );
198   if( capability == WL_EGL_WINDOW_CAPABILITY_ROTATION_SUPPORTED )
199   {
200     DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::CreateEglSurface: capability = %d\n", capability );
201     mRotationSupported = true;
202   }
203 }
204
205 void WindowRenderSurface::DestroyEglSurface( EglInterface& eglIf )
206 {
207   DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
208
209   Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( eglIf );
210   eglImpl.DestroySurface();
211
212   if( mEglWindow != NULL )
213   {
214     wl_egl_window_destroy(mEglWindow);
215     mEglWindow = NULL;
216   }
217 }
218
219 bool WindowRenderSurface::ReplaceEGLSurface( EglInterface& egl )
220 {
221   DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
222
223   if( mEglWindow != NULL )
224   {
225     wl_egl_window_destroy(mEglWindow);
226     mEglWindow = NULL;
227   }
228
229   // Temporary code for opaque window. We have to modify it after wayland team finish the work.
230   if( mColorDepth == COLOR_DEPTH_32 )
231   {
232     ecore_wl_window_alpha_set( mWlWindow, true );
233   }
234   else
235   {
236     ecore_wl_window_alpha_set( mWlWindow, false );
237   }
238
239   mEglWindow = wl_egl_window_create(ecore_wl_window_surface_get(mWlWindow), mPosition.width, mPosition.height);
240
241   Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
242   EGLNativeWindowType windowType( mEglWindow );
243   return eglImpl.ReplaceSurfaceWindow( windowType );
244 }
245
246 void WindowRenderSurface::MoveResize( Dali::PositionSize positionSize )
247 {
248   bool needToMove = false;
249   bool needToResize = false;
250
251   // check moving
252   if( (fabs(positionSize.x - mPosition.x) > MINIMUM_DIMENSION_CHANGE) ||
253       (fabs(positionSize.y - mPosition.y) > MINIMUM_DIMENSION_CHANGE) )
254   {
255     needToMove = true;
256   }
257
258   // check resizing
259   if( (fabs(positionSize.width - mPosition.width) > MINIMUM_DIMENSION_CHANGE) ||
260       (fabs(positionSize.height - mPosition.height) > MINIMUM_DIMENSION_CHANGE) )
261   {
262     needToResize = true;
263   }
264
265   if(needToMove)
266   {
267     ecore_wl_window_move(mWlWindow, positionSize.x, positionSize.y);
268     mPosition = positionSize;
269   }
270   if (needToResize)
271   {
272     ecore_wl_window_resize(mWlWindow, positionSize.width, positionSize.height, 0);
273     mPosition = positionSize;
274   }
275
276 }
277
278 void WindowRenderSurface::Map()
279 {
280   ecore_wl_window_show(mWlWindow);
281 }
282
283 void WindowRenderSurface::StartRender()
284 {
285 }
286
287 bool WindowRenderSurface::PreRender( EglInterface&, Integration::GlAbstraction& )
288 {
289   // nothing to do for windows
290   return true;
291 }
292
293 void WindowRenderSurface::PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, DisplayConnection* displayConnection, bool replacingSurface )
294 {
295   if( mRotated )
296   {
297     // Check viewport size
298     Dali::Vector< GLint > viewportSize;
299     viewportSize.Resize( 4 );
300
301     glAbstraction.GetIntegerv( GL_VIEWPORT, &viewportSize[0] );
302
303     if( viewportSize[2] == mPosition.width && viewportSize[3] == mPosition.height )
304     {
305       DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PostRender: Trigger rotation event\n" );
306
307       mRotationTrigger->Trigger();
308
309       if( mThreadSynchronization )
310       {
311         // Wait until the event-thread complete the rotation event processing
312         mThreadSynchronization->PostRenderWaitForCompletion();
313       }
314     }
315   }
316
317   Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
318   eglImpl.SwapBuffers();
319
320   if( mRenderNotification )
321   {
322     mRenderNotification->Trigger();
323   }
324 }
325
326 void WindowRenderSurface::StopRender()
327 {
328 }
329
330 void WindowRenderSurface::SetViewMode( ViewMode viewMode )
331 {
332   //FIXME
333 }
334
335 void WindowRenderSurface::CreateWlRenderable()
336 {
337    // if width or height are zero, go full screen.
338   if ( (mPosition.width == 0) || (mPosition.height == 0) )
339   {
340     // Default window size == screen size
341     mPosition.x = 0;
342     mPosition.y = 0;
343
344     ecore_wl_screen_size_get( &mPosition.width, &mPosition.height );
345   }
346
347   mWlWindow = ecore_wl_window_new( 0, mPosition.x, mPosition.y, mPosition.width, mPosition.height, ECORE_WL_WINDOW_BUFFER_TYPE_EGL_WINDOW );
348
349   if ( mWlWindow == 0 )
350   {
351     DALI_ASSERT_ALWAYS(0 && "Failed to create Wayland window");
352   }
353 }
354
355 void WindowRenderSurface::UseExistingRenderable( unsigned int surfaceId )
356 {
357   mWlWindow = AnyCast< Ecore_Wl_Window* >( surfaceId );
358 }
359
360 void WindowRenderSurface::SetThreadSynchronization( ThreadSynchronizationInterface& threadSynchronization )
361 {
362   DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::SetThreadSynchronization: called\n" );
363
364   mThreadSynchronization = &threadSynchronization;
365 }
366
367 void WindowRenderSurface::ReleaseLock()
368 {
369   // Nothing to do.
370 }
371
372 void WindowRenderSurface::ProcessRotationRequest()
373 {
374   mRotated = false;
375
376   ecore_wl_window_rotation_change_done_send( mWlWindow );
377
378   DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::ProcessRotationRequest: Rotation Done\n" );
379
380   if( mThreadSynchronization )
381   {
382     mThreadSynchronization->PostRenderComplete();
383   }
384 }
385
386 } // namespace ECore
387
388 } // namespace Dali