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