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