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