Revert "[Tizen] Implement partial update"
[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     mResizeFinished = false;
121   }
122 }
123
124 Any WindowRenderSurface::GetNativeWindow()
125 {
126   return mWindowBase->GetNativeWindow();
127 }
128
129 int WindowRenderSurface::GetNativeWindowId()
130 {
131   return mWindowBase->GetNativeWindowId();
132 }
133
134 void WindowRenderSurface::Map()
135 {
136   mWindowBase->Show();
137 }
138
139 void WindowRenderSurface::SetRenderNotification( TriggerEventInterface* renderNotification )
140 {
141   mRenderNotification = renderNotification;
142 }
143
144 void WindowRenderSurface::SetTransparency( bool transparent )
145 {
146   mWindowBase->SetTransparency( transparent );
147 }
148
149 void WindowRenderSurface::RequestRotation( int angle, int width, int height )
150 {
151   if( !mRotationTrigger )
152   {
153     TriggerEventFactoryInterface& triggerFactory = Internal::Adaptor::Adaptor::GetImplementation( Adaptor::Get() ).GetTriggerEventFactoryInterface();
154     mRotationTrigger = triggerFactory.CreateTriggerEvent( MakeCallback( this, &WindowRenderSurface::ProcessRotationRequest ), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER );
155   }
156
157   mPositionSize.width = width;
158   mPositionSize.height = height;
159
160   mRotationAngle = angle;
161   mRotationFinished = false;
162
163   mWindowBase->SetWindowRotationAngle( mRotationAngle );
164
165   DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::Rotate: angle = %d screen rotation = %d\n", mRotationAngle, mScreenRotationAngle );
166 }
167
168 WindowBase* WindowRenderSurface::GetWindowBase()
169 {
170   return mWindowBase.get();
171 }
172
173 WindowBase::OutputSignalType& WindowRenderSurface::OutputTransformedSignal()
174 {
175   return mOutputTransformedSignal;
176 }
177
178 PositionSize WindowRenderSurface::GetPositionSize() const
179 {
180   return mPositionSize;
181 }
182
183 void WindowRenderSurface::GetDpi( unsigned int& dpiHorizontal, unsigned int& dpiVertical )
184 {
185   if( mDpiHorizontal == 0 || mDpiVertical == 0 )
186   {
187     const char* environmentDpiHorizontal = std::getenv( DALI_ENV_DPI_HORIZONTAL );
188     mDpiHorizontal = environmentDpiHorizontal ? std::atoi( environmentDpiHorizontal ) : 0;
189
190     const char* environmentDpiVertical = std::getenv( DALI_ENV_DPI_VERTICAL );
191     mDpiVertical = environmentDpiVertical ? std::atoi( environmentDpiVertical ) : 0;
192
193     if( mDpiHorizontal == 0 || mDpiVertical == 0 )
194     {
195       mWindowBase->GetDpi( mDpiHorizontal, mDpiVertical );
196     }
197   }
198
199   dpiHorizontal = mDpiHorizontal;
200   dpiVertical = mDpiVertical;
201 }
202
203 int WindowRenderSurface::GetOrientation() const
204 {
205   return mWindowBase->GetOrientation();
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     int totalAngle = (mRotationAngle + mScreenRotationAngle) % 360;
361
362     // Window rotate or screen rotate
363     if( !mRotationFinished || !mScreenRotationFinished )
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       Dali::PositionSize positionSize;
384       positionSize.x = mPositionSize.x;
385       positionSize.y = mPositionSize.y;
386       if( totalAngle == 0 || totalAngle == 180 )
387       {
388         positionSize.width = mPositionSize.width;
389         positionSize.height = mPositionSize.height;
390       }
391       else
392       {
393         positionSize.width = mPositionSize.height;
394         positionSize.height = mPositionSize.width;
395       }
396
397       mWindowBase->ResizeEglWindow( positionSize );
398       mResizeFinished = true;
399
400       DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PreRender: Set resize\n" );
401     }
402   }
403
404   auto eglGraphics = static_cast<EglGraphics *>(mGraphics);
405   if ( eglGraphics )
406   {
407     GlImplementation& mGLES = eglGraphics->GetGlesInterface();
408     mGLES.PreRender();
409   }
410
411   return true;
412 }
413
414 void WindowRenderSurface::PostRender( bool renderToFbo, bool replacingSurface, bool resizingSurface )
415 {
416   // Inform the gl implementation that rendering has finished before informing the surface
417   auto eglGraphics = static_cast<EglGraphics *>(mGraphics);
418   if ( eglGraphics )
419   {
420     GlImplementation& mGLES = eglGraphics->GetGlesInterface();
421     mGLES.PostRender();
422
423     if( renderToFbo )
424     {
425       mGLES.Flush();
426       mGLES.Finish();
427     }
428     else
429     {
430       if( resizingSurface )
431       {
432         if( !mRotationFinished )
433         {
434           DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PostRender: Trigger rotation event\n" );
435
436           mRotationTrigger->Trigger();
437
438           if( mThreadSynchronization )
439           {
440             // Wait until the event-thread complete the rotation event processing
441             mThreadSynchronization->PostRenderWaitForCompletion();
442           }
443         }
444       }
445     }
446
447     Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
448     eglImpl.SwapBuffers( mEGLSurface );
449
450     if( mRenderNotification )
451     {
452       mRenderNotification->Trigger();
453     }
454   }
455 }
456
457 void WindowRenderSurface::StopRender()
458 {
459 }
460
461 void WindowRenderSurface::SetThreadSynchronization( ThreadSynchronizationInterface& threadSynchronization )
462 {
463   DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::SetThreadSynchronization: called\n" );
464
465   mThreadSynchronization = &threadSynchronization;
466 }
467
468 void WindowRenderSurface::ReleaseLock()
469 {
470   // Nothing to do.
471 }
472
473 Integration::RenderSurface::Type WindowRenderSurface::GetSurfaceType()
474 {
475   return RenderSurface::WINDOW_RENDER_SURFACE;
476 }
477
478 void WindowRenderSurface::MakeContextCurrent()
479 {
480   if ( mEGL != nullptr )
481   {
482     mEGL->MakeContextCurrent( mEGLSurface, mEGLContext );
483   }
484 }
485
486 Integration::DepthBufferAvailable WindowRenderSurface::GetDepthBufferRequired()
487 {
488   return mGraphics ? mGraphics->GetDepthBufferRequired() : Integration::DepthBufferAvailable::FALSE;
489 }
490
491 Integration::StencilBufferAvailable WindowRenderSurface::GetStencilBufferRequired()
492 {
493   return mGraphics ? mGraphics->GetStencilBufferRequired() : Integration::StencilBufferAvailable::FALSE;
494 }
495
496 void WindowRenderSurface::OutputTransformed()
497 {
498   int screenRotationAngle = mWindowBase->GetScreenRotationAngle();
499
500   if( mScreenRotationAngle != screenRotationAngle )
501   {
502     mScreenRotationAngle = screenRotationAngle;
503     mScreenRotationFinished = false;
504     mResizeFinished = false;
505
506     mOutputTransformedSignal.Emit();
507
508     DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::OutputTransformed: angle = %d screen rotation = %d\n", mRotationAngle, mScreenRotationAngle );
509   }
510   else
511   {
512     DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::OutputTransformed: Ignore output transform [%d]\n", mScreenRotationAngle );
513   }
514 }
515
516 void WindowRenderSurface::ProcessRotationRequest()
517 {
518   mRotationFinished = true;
519
520   mWindowBase->WindowRotationCompleted( mRotationAngle, mPositionSize.width, mPositionSize.height );
521
522   DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::ProcessRotationRequest: Rotation Done\n" );
523
524   if( mThreadSynchronization )
525   {
526     mThreadSynchronization->PostRenderComplete();
527   }
528 }
529
530 } // namespace Adaptor
531
532 } // namespace internal
533
534 } // namespace Dali