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