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