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