Initialize EGL and DiplayConnection
[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/gles/egl-implementation.h>
29 #include <dali/internal/adaptor/common/adaptor-impl.h>
30 #include <dali/internal/adaptor/common/adaptor-internal-services.h>
31 #include <dali/internal/window-system/common/window-base.h>
32 #include <dali/internal/window-system/common/window-factory.h>
33 #include <dali/internal/window-system/common/window-system.h>
34 #include <dali/internal/graphics/gles/egl-graphics.h>
35
36
37 namespace Dali
38 {
39 namespace Internal
40 {
41 namespace Adaptor
42 {
43
44 namespace
45 {
46
47 const int MINIMUM_DIMENSION_CHANGE( 1 ); ///< Minimum change for window to be considered to have moved
48
49 #if defined(DEBUG_ENABLED)
50 Debug::Filter* gWindowRenderSurfaceLogFilter = Debug::Filter::New(Debug::Verbose, false, "LOG_WINDOW_RENDER_SURFACE");
51 #endif
52
53 } // unnamed namespace
54
55 WindowRenderSurface::WindowRenderSurface( Dali::PositionSize positionSize, Any surface, bool isTransparent )
56 : mEGL( nullptr ),
57   mDisplayConnection( nullptr ),
58   mPositionSize( positionSize ),
59   mWindowBase(),
60   mThreadSynchronization( NULL ),
61   mRenderNotification( NULL ),
62   mRotationTrigger( NULL ),
63   mGraphics( nullptr ),
64   mEGLSurface( nullptr ),
65   mEGLContext( nullptr ),
66   mColorDepth( isTransparent ? COLOR_DEPTH_32 : COLOR_DEPTH_24 ),
67   mOutputTransformedSignal(),
68   mRotationAngle( 0 ),
69   mScreenRotationAngle( 0 ),
70   mOwnSurface( false ),
71   mRotationSupported( false ),
72   mRotationFinished( true ),
73   mScreenRotationFinished( true ),
74   mResizeFinished( true )
75 {
76   DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "Creating Window\n" );
77   Initialize( surface );
78 }
79
80 WindowRenderSurface::~WindowRenderSurface()
81 {
82   if( mRotationTrigger )
83   {
84     delete mRotationTrigger;
85   }
86 }
87
88 void WindowRenderSurface::Initialize( Any surface )
89 {
90   // If width or height are zero, go full screen.
91   if ( (mPositionSize.width == 0) || (mPositionSize.height == 0) )
92   {
93     // Default window size == screen size
94     mPositionSize.x = 0;
95     mPositionSize.y = 0;
96
97     WindowSystem::GetScreenSize( mPositionSize.width, mPositionSize.height );
98   }
99
100   // Create a window base
101   auto windowFactory = Dali::Internal::Adaptor::GetWindowFactory();
102   mWindowBase = windowFactory->CreateWindowBase( mPositionSize, surface, ( mColorDepth == COLOR_DEPTH_32 ? true : false ) );
103
104   // Connect signals
105   mWindowBase->OutputTransformedSignal().Connect( this, &WindowRenderSurface::OutputTransformed );
106
107   // Check screen rotation
108   mScreenRotationAngle = mWindowBase->GetScreenRotationAngle();
109   if( mScreenRotationAngle != 0 )
110   {
111     mScreenRotationFinished = false;
112   }
113 }
114
115 Any WindowRenderSurface::GetNativeWindow()
116 {
117   return mWindowBase->GetNativeWindow();
118 }
119
120 int WindowRenderSurface::GetNativeWindowId()
121 {
122   return mWindowBase->GetNativeWindowId();
123 }
124
125 void WindowRenderSurface::Map()
126 {
127   mWindowBase->Show();
128 }
129
130 void WindowRenderSurface::SetRenderNotification( TriggerEventInterface* renderNotification )
131 {
132   mRenderNotification = renderNotification;
133 }
134
135 void WindowRenderSurface::SetTransparency( bool transparent )
136 {
137   mWindowBase->SetTransparency( transparent );
138 }
139
140 void WindowRenderSurface::RequestRotation( int angle, int width, int height )
141 {
142   if( !mRotationSupported )
143   {
144     DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::Rotate: Rotation is not supported!\n" );
145     return;
146   }
147
148   if( !mRotationTrigger )
149   {
150     TriggerEventFactoryInterface& triggerFactory = Internal::Adaptor::Adaptor::GetImplementation( Adaptor::Get() ).GetTriggerEventFactoryInterface();
151     mRotationTrigger = triggerFactory.CreateTriggerEvent( MakeCallback( this, &WindowRenderSurface::ProcessRotationRequest ), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER );
152   }
153
154   mPositionSize.width = width;
155   mPositionSize.height = height;
156
157   mRotationAngle = angle;
158   mRotationFinished = false;
159
160   mWindowBase->SetWindowRotationAngle( mRotationAngle );
161
162   DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::Rotate: angle = %d screen rotation = %d\n", mRotationAngle, mScreenRotationAngle );
163 }
164
165 WindowBase* WindowRenderSurface::GetWindowBase()
166 {
167   return mWindowBase.get();
168 }
169
170 WindowBase::OutputSignalType& WindowRenderSurface::OutputTransformedSignal()
171 {
172   return mOutputTransformedSignal;
173 }
174
175 PositionSize WindowRenderSurface::GetPositionSize() const
176 {
177   return mPositionSize;
178 }
179
180 void WindowRenderSurface::GetDpi( unsigned int& dpiHorizontal, unsigned int& dpiVertical )
181 {
182   mWindowBase->GetDpi( dpiHorizontal, dpiVertical );
183 }
184
185 void WindowRenderSurface::InitializeGraphics()
186 {
187
188   mGraphics = &mAdaptor->GetGraphicsInterface();
189
190   auto eglGraphics = static_cast<EglGraphics *>(mGraphics);
191   mEGL = &eglGraphics->GetEglInterface();
192
193   if ( mEGLContext == NULL )
194   {
195     // Create the OpenGL context for this window
196     Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>(*mEGL);
197     eglImpl.ChooseConfig(true, mColorDepth);
198     eglImpl.CreateWindowContext( mEGLContext );
199
200     // Create the OpenGL surface
201     CreateSurface();
202   }
203 }
204
205 void WindowRenderSurface::CreateSurface()
206 {
207   DALI_LOG_TRACE_METHOD( gWindowRenderSurfaceLogFilter );
208
209   int width, height;
210   if( mScreenRotationAngle == 0 || mScreenRotationAngle == 180 )
211   {
212     width = mPositionSize.width;
213     height = mPositionSize.height;
214   }
215   else
216   {
217     width = mPositionSize.height;
218     height = mPositionSize.width;
219   }
220
221   // Create the EGL window
222   EGLNativeWindowType window = mWindowBase->CreateEglWindow( width, height );
223
224   auto eglGraphics = static_cast<EglGraphics *>(mGraphics);
225
226   Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
227   mEGLSurface = eglImpl.CreateSurfaceWindow( window, mColorDepth );
228
229   // Check rotation capability
230   mRotationSupported = mWindowBase->IsEglWindowRotationSupported();
231
232   DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::CreateSurface: w = %d h = %d angle = %d screen rotation = %d\n", mPositionSize.width, mPositionSize.height, mRotationAngle, mScreenRotationAngle );
233 }
234
235 void WindowRenderSurface::DestroySurface()
236 {
237   DALI_LOG_TRACE_METHOD( gWindowRenderSurfaceLogFilter );
238
239   auto eglGraphics = static_cast<EglGraphics *>(mGraphics);
240
241   Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
242   eglImpl.DestroySurface( mEGLSurface );
243
244   mWindowBase->DestroyEglWindow();
245 }
246
247 bool WindowRenderSurface::ReplaceGraphicsSurface()
248 {
249   DALI_LOG_TRACE_METHOD( gWindowRenderSurfaceLogFilter );
250
251   // Destroy the old one
252   mWindowBase->DestroyEglWindow();
253
254   int width, height;
255   if( mScreenRotationAngle == 0 || mScreenRotationAngle == 180 )
256   {
257     width = mPositionSize.width;
258     height = mPositionSize.height;
259   }
260   else
261   {
262     width = mPositionSize.height;
263     height = mPositionSize.width;
264   }
265
266   // Create the EGL window
267   EGLNativeWindowType window = mWindowBase->CreateEglWindow( width, height );
268
269   // Set screen rotation
270   mScreenRotationFinished = false;
271
272   auto eglGraphics = static_cast<EglGraphics *>(mGraphics);
273
274   Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
275   return eglImpl.ReplaceSurfaceWindow( window, mEGLSurface, mEGLContext );
276 }
277
278 void WindowRenderSurface::MoveResize( Dali::PositionSize positionSize )
279 {
280   bool needToMove = false;
281   bool needToResize = false;
282
283   // Check moving
284   if( (fabs(positionSize.x - mPositionSize.x) > MINIMUM_DIMENSION_CHANGE) ||
285       (fabs(positionSize.y - mPositionSize.y) > MINIMUM_DIMENSION_CHANGE) )
286   {
287     needToMove = true;
288   }
289
290   // Check resizing
291   if( (fabs(positionSize.width - mPositionSize.width) > MINIMUM_DIMENSION_CHANGE) ||
292       (fabs(positionSize.height - mPositionSize.height) > MINIMUM_DIMENSION_CHANGE) )
293   {
294     needToResize = true;
295   }
296
297   if( needToResize )
298   {
299     if( needToMove )
300     {
301       mWindowBase->MoveResize( positionSize );
302     }
303     else
304     {
305       mWindowBase->Resize( positionSize );
306     }
307
308     mResizeFinished = false;
309     mPositionSize = positionSize;
310   }
311   else
312   {
313     if( needToMove )
314     {
315       mWindowBase->Move( positionSize );
316
317       mPositionSize = positionSize;
318     }
319   }
320
321   DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::MoveResize: %d, %d, %d, %d\n", mPositionSize.x, mPositionSize.y, mPositionSize.width, mPositionSize.height );
322 }
323
324 void WindowRenderSurface::StartRender()
325 {
326 }
327
328 bool WindowRenderSurface::PreRender( bool resizingSurface )
329 {
330   MakeContextCurrent();
331
332   if( resizingSurface )
333   {
334 #ifdef OVER_TIZEN_VERSION_4
335     // Window rotate or screen rotate
336     if( !mRotationFinished || !mScreenRotationFinished )
337     {
338       int totalAngle = (mRotationAngle + mScreenRotationAngle) % 360;
339
340       mWindowBase->SetEglWindowRotation( totalAngle );
341       mWindowBase->SetEglWindowBufferTransform( totalAngle );
342
343       // Reset only screen rotation flag
344       mScreenRotationFinished = true;
345
346       DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PreRender: Set rotation [%d] [%d]\n", mRotationAngle, mScreenRotationAngle );
347     }
348
349     // Only window rotate
350     if( !mRotationFinished )
351     {
352       mWindowBase->SetEglWindowTransform( mRotationAngle );
353     }
354 #endif
355
356     // Resize case
357     if( !mResizeFinished )
358     {
359       mWindowBase->ResizeEglWindow( mPositionSize );
360       mResizeFinished = true;
361
362       DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PreRender: Set resize\n" );
363     }
364   }
365
366   auto eglGraphics = static_cast<EglGraphics *>(mGraphics);
367   if ( eglGraphics )
368   {
369     GlImplementation& mGLES = eglGraphics->GetGlesInterface();
370     mGLES.PreRender();
371   }
372
373   return true;
374 }
375
376 void WindowRenderSurface::PostRender( bool renderToFbo, bool replacingSurface, bool resizingSurface )
377 {
378   // Inform the gl implementation that rendering has finished before informing the surface
379   auto eglGraphics = static_cast<EglGraphics *>(mGraphics);
380   if ( eglGraphics )
381   {
382     GlImplementation& mGLES = eglGraphics->GetGlesInterface();
383     mGLES.PostRender();
384
385     if( renderToFbo )
386     {
387       mGLES.Flush();
388       mGLES.Finish();
389     }
390     else
391     {
392       if( resizingSurface )
393       {
394         if( !mRotationFinished )
395         {
396           DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PostRender: Trigger rotation event\n" );
397
398           mRotationTrigger->Trigger();
399
400           if( mThreadSynchronization )
401           {
402             // Wait until the event-thread complete the rotation event processing
403             mThreadSynchronization->PostRenderWaitForCompletion();
404           }
405         }
406       }
407     }
408
409     Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
410     eglImpl.SwapBuffers( mEGLSurface );
411
412     if( mRenderNotification )
413     {
414       mRenderNotification->Trigger();
415     }
416   }
417 }
418
419 void WindowRenderSurface::StopRender()
420 {
421 }
422
423 void WindowRenderSurface::SetThreadSynchronization( ThreadSynchronizationInterface& threadSynchronization )
424 {
425   DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::SetThreadSynchronization: called\n" );
426
427   mThreadSynchronization = &threadSynchronization;
428 }
429
430 void WindowRenderSurface::ReleaseLock()
431 {
432   // Nothing to do.
433 }
434
435 Integration::RenderSurface::Type WindowRenderSurface::GetSurfaceType()
436 {
437   return RenderSurface::WINDOW_RENDER_SURFACE;
438 }
439
440 void WindowRenderSurface::MakeContextCurrent()
441 {
442   if ( mEGL != nullptr )
443   {
444     mEGL->MakeContextCurrent( mEGLSurface, mEGLContext );
445   }
446 }
447
448 Integration::DepthBufferAvailable WindowRenderSurface::GetDepthBufferRequired()
449 {
450   return mGraphics ? mGraphics->GetDepthBufferRequired() : Integration::DepthBufferAvailable::FALSE;
451 }
452
453 Integration::StencilBufferAvailable WindowRenderSurface::GetStencilBufferRequired()
454 {
455   return mGraphics ? mGraphics->GetStencilBufferRequired() : Integration::StencilBufferAvailable::FALSE;
456 }
457
458 void WindowRenderSurface::OutputTransformed()
459 {
460   int screenRotationAngle = mWindowBase->GetScreenRotationAngle();
461
462   if( mScreenRotationAngle != screenRotationAngle )
463   {
464     mScreenRotationAngle = screenRotationAngle;
465     mScreenRotationFinished = false;
466
467     mOutputTransformedSignal.Emit();
468
469     DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::OutputTransformed: angle = %d screen rotation = %d\n", mRotationAngle, mScreenRotationAngle );
470   }
471   else
472   {
473     DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::OutputTransformed: Ignore output transform [%d]\n", mScreenRotationAngle );
474   }
475 }
476
477 void WindowRenderSurface::ProcessRotationRequest()
478 {
479   mRotationFinished = true;
480
481   mWindowBase->WindowRotationCompleted( mRotationAngle, mPositionSize.width, mPositionSize.height );
482
483   DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::ProcessRotationRequest: Rotation Done\n" );
484
485   if( mThreadSynchronization )
486   {
487     mThreadSynchronization->PostRenderComplete();
488   }
489 }
490
491 } // namespace Adaptor
492
493 } // namespace internal
494
495 } // namespace Dali