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