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
104     WindowSystem::GetScreenSize( mPositionSize.width, mPositionSize.height );
105   }
106
107   // Create a window base
108   auto windowFactory = Dali::Internal::Adaptor::GetWindowFactory();
109   mWindowBase = windowFactory->CreateWindowBase( mPositionSize, surface, ( mColorDepth == COLOR_DEPTH_32 ? true : false ) );
110
111   // Connect signals
112   mWindowBase->OutputTransformedSignal().Connect( this, &WindowRenderSurface::OutputTransformed );
113
114   // Check screen rotation
115   mScreenRotationAngle = mWindowBase->GetScreenRotationAngle();
116   if( mScreenRotationAngle != 0 )
117   {
118     mScreenRotationFinished = false;
119     mResizeFinished = 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( !mRotationTrigger )
151   {
152     TriggerEventFactoryInterface& triggerFactory = Internal::Adaptor::Adaptor::GetImplementation( Adaptor::Get() ).GetTriggerEventFactoryInterface();
153     mRotationTrigger = triggerFactory.CreateTriggerEvent( MakeCallback( this, &WindowRenderSurface::ProcessRotationRequest ), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER );
154   }
155
156   mPositionSize.width = width;
157   mPositionSize.height = height;
158
159   mRotationAngle = angle;
160   mRotationFinished = false;
161
162   mWindowBase->SetWindowRotationAngle( mRotationAngle );
163
164   DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::Rotate: angle = %d screen rotation = %d\n", mRotationAngle, mScreenRotationAngle );
165 }
166
167 WindowBase* WindowRenderSurface::GetWindowBase()
168 {
169   return mWindowBase.get();
170 }
171
172 WindowBase::OutputSignalType& WindowRenderSurface::OutputTransformedSignal()
173 {
174   return mOutputTransformedSignal;
175 }
176
177 PositionSize WindowRenderSurface::GetPositionSize() const
178 {
179   return mPositionSize;
180 }
181
182 void WindowRenderSurface::GetDpi( unsigned int& dpiHorizontal, unsigned int& dpiVertical )
183 {
184   if( mDpiHorizontal == 0 || mDpiVertical == 0 )
185   {
186     const char* environmentDpiHorizontal = std::getenv( DALI_ENV_DPI_HORIZONTAL );
187     mDpiHorizontal = environmentDpiHorizontal ? std::atoi( environmentDpiHorizontal ) : 0;
188
189     const char* environmentDpiVertical = std::getenv( DALI_ENV_DPI_VERTICAL );
190     mDpiVertical = environmentDpiVertical ? std::atoi( environmentDpiVertical ) : 0;
191
192     if( mDpiHorizontal == 0 || mDpiVertical == 0 )
193     {
194       mWindowBase->GetDpi( mDpiHorizontal, mDpiVertical );
195     }
196   }
197
198   dpiHorizontal = mDpiHorizontal;
199   dpiVertical = mDpiVertical;
200 }
201
202 int WindowRenderSurface::GetOrientation() const
203 {
204   return mWindowBase->GetOrientation();
205 }
206
207 void WindowRenderSurface::InitializeGraphics()
208 {
209
210   mGraphics = &mAdaptor->GetGraphicsInterface();
211
212   auto eglGraphics = static_cast<EglGraphics *>(mGraphics);
213   mEGL = &eglGraphics->GetEglInterface();
214
215   if ( mEGLContext == NULL )
216   {
217     // Create the OpenGL context for this window
218     Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>(*mEGL);
219     eglImpl.ChooseConfig(true, mColorDepth);
220     eglImpl.CreateWindowContext( mEGLContext );
221
222     // Create the OpenGL surface
223     CreateSurface();
224   }
225 }
226
227 void WindowRenderSurface::CreateSurface()
228 {
229   DALI_LOG_TRACE_METHOD( gWindowRenderSurfaceLogFilter );
230
231   int width, height;
232   if( mScreenRotationAngle == 0 || mScreenRotationAngle == 180 )
233   {
234     width = mPositionSize.width;
235     height = mPositionSize.height;
236   }
237   else
238   {
239     width = mPositionSize.height;
240     height = mPositionSize.width;
241   }
242
243   // Create the EGL window
244   EGLNativeWindowType window = mWindowBase->CreateEglWindow( width, height );
245
246   auto eglGraphics = static_cast<EglGraphics *>(mGraphics);
247
248   Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
249   mEGLSurface = eglImpl.CreateSurfaceWindow( window, mColorDepth );
250
251   // Check rotation capability
252   mRotationSupported = mWindowBase->IsEglWindowRotationSupported();
253
254   DALI_LOG_RELEASE_INFO("WindowRenderSurface::CreateSurface: w = %d h = %d angle = %d screen rotation = %d\n",
255       mPositionSize.width, mPositionSize.height, mRotationAngle, mScreenRotationAngle );
256 }
257
258 void WindowRenderSurface::DestroySurface()
259 {
260   DALI_LOG_TRACE_METHOD( gWindowRenderSurfaceLogFilter );
261
262   auto eglGraphics = static_cast<EglGraphics *>(mGraphics);
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           DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PostRender: Trigger rotation event\n" );
432
433           mRotationTrigger->Trigger();
434
435           if( mThreadSynchronization )
436           {
437             // Wait until the event-thread complete the rotation event processing
438             mThreadSynchronization->PostRenderWaitForCompletion();
439           }
440         }
441       }
442     }
443
444     Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
445     eglImpl.SwapBuffers( mEGLSurface );
446
447     if( mRenderNotification )
448     {
449       mRenderNotification->Trigger();
450     }
451   }
452 }
453
454 void WindowRenderSurface::StopRender()
455 {
456 }
457
458 void WindowRenderSurface::SetThreadSynchronization( ThreadSynchronizationInterface& threadSynchronization )
459 {
460   DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::SetThreadSynchronization: called\n" );
461
462   mThreadSynchronization = &threadSynchronization;
463 }
464
465 void WindowRenderSurface::ReleaseLock()
466 {
467   // Nothing to do.
468 }
469
470 Integration::RenderSurface::Type WindowRenderSurface::GetSurfaceType()
471 {
472   return RenderSurface::WINDOW_RENDER_SURFACE;
473 }
474
475 void WindowRenderSurface::MakeContextCurrent()
476 {
477   if ( mEGL != nullptr )
478   {
479     mEGL->MakeContextCurrent( mEGLSurface, mEGLContext );
480   }
481 }
482
483 Integration::DepthBufferAvailable WindowRenderSurface::GetDepthBufferRequired()
484 {
485   return mGraphics ? mGraphics->GetDepthBufferRequired() : Integration::DepthBufferAvailable::FALSE;
486 }
487
488 Integration::StencilBufferAvailable WindowRenderSurface::GetStencilBufferRequired()
489 {
490   return mGraphics ? mGraphics->GetStencilBufferRequired() : Integration::StencilBufferAvailable::FALSE;
491 }
492
493 void WindowRenderSurface::OutputTransformed()
494 {
495   int screenRotationAngle = mWindowBase->GetScreenRotationAngle();
496
497   if( mScreenRotationAngle != screenRotationAngle )
498   {
499     mScreenRotationAngle = screenRotationAngle;
500     mScreenRotationFinished = false;
501     mResizeFinished = false;
502
503     mOutputTransformedSignal.Emit();
504
505     DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::OutputTransformed: angle = %d screen rotation = %d\n", mRotationAngle, mScreenRotationAngle );
506   }
507   else
508   {
509     DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::OutputTransformed: Ignore output transform [%d]\n", mScreenRotationAngle );
510   }
511 }
512
513 void WindowRenderSurface::ProcessRotationRequest()
514 {
515   mRotationFinished = true;
516
517   mWindowBase->WindowRotationCompleted( mRotationAngle, mPositionSize.width, mPositionSize.height );
518
519   DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::ProcessRotationRequest: Rotation Done\n" );
520
521   if( mThreadSynchronization )
522   {
523     mThreadSynchronization->PostRenderComplete();
524   }
525 }
526
527 } // namespace Adaptor
528
529 } // namespace internal
530
531 } // namespace Dali