Merge "Remove CXX03 Build & old Tizen Version Builds" into devel/master
[platform/core/uifw/dali-adaptor.git] / dali / internal / window-system / common / window-render-surface.cpp
1 /*
2  * Copyright (c) 2019 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     // Window rotate or screen rotate
335     if( !mRotationFinished || !mScreenRotationFinished )
336     {
337       int totalAngle = (mRotationAngle + mScreenRotationAngle) % 360;
338
339       mWindowBase->SetEglWindowRotation( totalAngle );
340       mWindowBase->SetEglWindowBufferTransform( totalAngle );
341
342       // Reset only screen rotation flag
343       mScreenRotationFinished = true;
344
345       DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PreRender: Set rotation [%d] [%d]\n", mRotationAngle, mScreenRotationAngle );
346     }
347
348     // Only window rotate
349     if( !mRotationFinished )
350     {
351       mWindowBase->SetEglWindowTransform( mRotationAngle );
352     }
353
354     // Resize case
355     if( !mResizeFinished )
356     {
357       mWindowBase->ResizeEglWindow( mPositionSize );
358       mResizeFinished = true;
359
360       DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PreRender: Set resize\n" );
361     }
362   }
363
364   auto eglGraphics = static_cast<EglGraphics *>(mGraphics);
365   if ( eglGraphics )
366   {
367     GlImplementation& mGLES = eglGraphics->GetGlesInterface();
368     mGLES.PreRender();
369   }
370
371   return true;
372 }
373
374 void WindowRenderSurface::PostRender( bool renderToFbo, bool replacingSurface, bool resizingSurface )
375 {
376   // Inform the gl implementation that rendering has finished before informing the surface
377   auto eglGraphics = static_cast<EglGraphics *>(mGraphics);
378   if ( eglGraphics )
379   {
380     GlImplementation& mGLES = eglGraphics->GetGlesInterface();
381     mGLES.PostRender();
382
383     if( renderToFbo )
384     {
385       mGLES.Flush();
386       mGLES.Finish();
387     }
388     else
389     {
390       if( resizingSurface )
391       {
392         if( !mRotationFinished )
393         {
394           DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, 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
407     Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
408     eglImpl.SwapBuffers( mEGLSurface );
409
410     if( mRenderNotification )
411     {
412       mRenderNotification->Trigger();
413     }
414   }
415 }
416
417 void WindowRenderSurface::StopRender()
418 {
419 }
420
421 void WindowRenderSurface::SetThreadSynchronization( ThreadSynchronizationInterface& threadSynchronization )
422 {
423   DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::SetThreadSynchronization: called\n" );
424
425   mThreadSynchronization = &threadSynchronization;
426 }
427
428 void WindowRenderSurface::ReleaseLock()
429 {
430   // Nothing to do.
431 }
432
433 Integration::RenderSurface::Type WindowRenderSurface::GetSurfaceType()
434 {
435   return RenderSurface::WINDOW_RENDER_SURFACE;
436 }
437
438 void WindowRenderSurface::MakeContextCurrent()
439 {
440   if ( mEGL != nullptr )
441   {
442     mEGL->MakeContextCurrent( mEGLSurface, mEGLContext );
443   }
444 }
445
446 Integration::DepthBufferAvailable WindowRenderSurface::GetDepthBufferRequired()
447 {
448   return mGraphics ? mGraphics->GetDepthBufferRequired() : Integration::DepthBufferAvailable::FALSE;
449 }
450
451 Integration::StencilBufferAvailable WindowRenderSurface::GetStencilBufferRequired()
452 {
453   return mGraphics ? mGraphics->GetStencilBufferRequired() : Integration::StencilBufferAvailable::FALSE;
454 }
455
456 void WindowRenderSurface::OutputTransformed()
457 {
458   int screenRotationAngle = mWindowBase->GetScreenRotationAngle();
459
460   if( mScreenRotationAngle != screenRotationAngle )
461   {
462     mScreenRotationAngle = screenRotationAngle;
463     mScreenRotationFinished = false;
464
465     mOutputTransformedSignal.Emit();
466
467     DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::OutputTransformed: angle = %d screen rotation = %d\n", mRotationAngle, mScreenRotationAngle );
468   }
469   else
470   {
471     DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::OutputTransformed: Ignore output transform [%d]\n", mScreenRotationAngle );
472   }
473 }
474
475 void WindowRenderSurface::ProcessRotationRequest()
476 {
477   mRotationFinished = true;
478
479   mWindowBase->WindowRotationCompleted( mRotationAngle, mPositionSize.width, mPositionSize.height );
480
481   DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::ProcessRotationRequest: Rotation Done\n" );
482
483   if( mThreadSynchronization )
484   {
485     mThreadSynchronization->PostRenderComplete();
486   }
487 }
488
489 } // namespace Adaptor
490
491 } // namespace internal
492
493 } // namespace Dali