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