2 * Copyright (c) 2019 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali/internal/window-system/common/window-render-surface.h>
22 #include <dali/integration-api/gl-abstraction.h>
23 #include <dali/integration-api/debug.h>
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>
47 const int MINIMUM_DIMENSION_CHANGE( 1 ); ///< Minimum change for window to be considered to have moved
49 #if defined(DEBUG_ENABLED)
50 Debug::Filter* gWindowRenderSurfaceLogFilter = Debug::Filter::New(Debug::Verbose, false, "LOG_WINDOW_RENDER_SURFACE");
53 } // unnamed namespace
55 WindowRenderSurface::WindowRenderSurface( Dali::PositionSize positionSize, Any surface, bool isTransparent )
57 mDisplayConnection( nullptr ),
58 mPositionSize( positionSize ),
60 mThreadSynchronization( NULL ),
61 mRenderNotification( NULL ),
62 mRotationTrigger( NULL ),
64 mEGLSurface( nullptr ),
65 mEGLContext( nullptr ),
66 mColorDepth( isTransparent ? COLOR_DEPTH_32 : COLOR_DEPTH_24 ),
67 mOutputTransformedSignal(),
69 mScreenRotationAngle( 0 ),
71 mRotationSupported( false ),
72 mRotationFinished( true ),
73 mScreenRotationFinished( true ),
74 mResizeFinished( true )
76 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "Creating Window\n" );
77 Initialize( surface );
80 WindowRenderSurface::~WindowRenderSurface()
82 if( mRotationTrigger )
84 delete mRotationTrigger;
93 void WindowRenderSurface::Initialize( Any surface )
95 // If width or height are zero, go full screen.
96 if ( (mPositionSize.width == 0) || (mPositionSize.height == 0) )
98 // Default window size == screen size
102 WindowSystem::GetScreenSize( mPositionSize.width, mPositionSize.height );
105 // Create a window base
106 auto windowFactory = Dali::Internal::Adaptor::GetWindowFactory();
107 mWindowBase = windowFactory->CreateWindowBase( mPositionSize, surface, ( mColorDepth == COLOR_DEPTH_32 ? true : false ) );
110 mWindowBase->OutputTransformedSignal().Connect( this, &WindowRenderSurface::OutputTransformed );
112 // Check screen rotation
113 mScreenRotationAngle = mWindowBase->GetScreenRotationAngle();
114 if( mScreenRotationAngle != 0 )
116 mScreenRotationFinished = false;
117 mResizeFinished = false;
121 Any WindowRenderSurface::GetNativeWindow()
123 return mWindowBase->GetNativeWindow();
126 int WindowRenderSurface::GetNativeWindowId()
128 return mWindowBase->GetNativeWindowId();
131 void WindowRenderSurface::Map()
136 void WindowRenderSurface::SetRenderNotification( TriggerEventInterface* renderNotification )
138 mRenderNotification = renderNotification;
141 void WindowRenderSurface::SetTransparency( bool transparent )
143 mWindowBase->SetTransparency( transparent );
146 void WindowRenderSurface::RequestRotation( int angle, int width, int height )
148 if( !mRotationTrigger )
150 TriggerEventFactoryInterface& triggerFactory = Internal::Adaptor::Adaptor::GetImplementation( Adaptor::Get() ).GetTriggerEventFactoryInterface();
151 mRotationTrigger = triggerFactory.CreateTriggerEvent( MakeCallback( this, &WindowRenderSurface::ProcessRotationRequest ), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER );
154 mPositionSize.width = width;
155 mPositionSize.height = height;
157 mRotationAngle = angle;
158 mRotationFinished = false;
160 mWindowBase->SetWindowRotationAngle( mRotationAngle );
162 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::Rotate: angle = %d screen rotation = %d\n", mRotationAngle, mScreenRotationAngle );
165 WindowBase* WindowRenderSurface::GetWindowBase()
167 return mWindowBase.get();
170 WindowBase::OutputSignalType& WindowRenderSurface::OutputTransformedSignal()
172 return mOutputTransformedSignal;
175 PositionSize WindowRenderSurface::GetPositionSize() const
177 return mPositionSize;
180 void WindowRenderSurface::GetDpi( unsigned int& dpiHorizontal, unsigned int& dpiVertical )
182 mWindowBase->GetDpi( dpiHorizontal, dpiVertical );
185 int WindowRenderSurface::GetOrientation() const
187 return mWindowBase->GetOrientation();
190 void WindowRenderSurface::InitializeGraphics()
193 mGraphics = &mAdaptor->GetGraphicsInterface();
195 auto eglGraphics = static_cast<EglGraphics *>(mGraphics);
196 mEGL = &eglGraphics->GetEglInterface();
198 if ( mEGLContext == NULL )
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 );
205 // Create the OpenGL surface
210 void WindowRenderSurface::CreateSurface()
212 DALI_LOG_TRACE_METHOD( gWindowRenderSurfaceLogFilter );
215 if( mScreenRotationAngle == 0 || mScreenRotationAngle == 180 )
217 width = mPositionSize.width;
218 height = mPositionSize.height;
222 width = mPositionSize.height;
223 height = mPositionSize.width;
226 // Create the EGL window
227 EGLNativeWindowType window = mWindowBase->CreateEglWindow( width, height );
229 auto eglGraphics = static_cast<EglGraphics *>(mGraphics);
231 Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
232 mEGLSurface = eglImpl.CreateSurfaceWindow( window, mColorDepth );
234 // Check rotation capability
235 mRotationSupported = mWindowBase->IsEglWindowRotationSupported();
237 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::CreateSurface: w = %d h = %d angle = %d screen rotation = %d\n", mPositionSize.width, mPositionSize.height, mRotationAngle, mScreenRotationAngle );
240 void WindowRenderSurface::DestroySurface()
242 DALI_LOG_TRACE_METHOD( gWindowRenderSurfaceLogFilter );
244 auto eglGraphics = static_cast<EglGraphics *>(mGraphics);
246 Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
247 eglImpl.DestroySurface( mEGLSurface );
249 mWindowBase->DestroyEglWindow();
252 bool WindowRenderSurface::ReplaceGraphicsSurface()
254 DALI_LOG_TRACE_METHOD( gWindowRenderSurfaceLogFilter );
256 // Destroy the old one
257 mWindowBase->DestroyEglWindow();
260 if( mScreenRotationAngle == 0 || mScreenRotationAngle == 180 )
262 width = mPositionSize.width;
263 height = mPositionSize.height;
267 width = mPositionSize.height;
268 height = mPositionSize.width;
271 // Create the EGL window
272 EGLNativeWindowType window = mWindowBase->CreateEglWindow( width, height );
274 // Set screen rotation
275 mScreenRotationFinished = false;
277 auto eglGraphics = static_cast<EglGraphics *>(mGraphics);
279 Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
280 return eglImpl.ReplaceSurfaceWindow( window, mEGLSurface, mEGLContext );
283 void WindowRenderSurface::MoveResize( Dali::PositionSize positionSize )
285 bool needToMove = false;
286 bool needToResize = false;
289 if( (fabs(positionSize.x - mPositionSize.x) > MINIMUM_DIMENSION_CHANGE) ||
290 (fabs(positionSize.y - mPositionSize.y) > MINIMUM_DIMENSION_CHANGE) )
296 if( (fabs(positionSize.width - mPositionSize.width) > MINIMUM_DIMENSION_CHANGE) ||
297 (fabs(positionSize.height - mPositionSize.height) > MINIMUM_DIMENSION_CHANGE) )
306 mWindowBase->MoveResize( positionSize );
310 mWindowBase->Resize( positionSize );
313 mResizeFinished = false;
314 mPositionSize = positionSize;
320 mWindowBase->Move( positionSize );
322 mPositionSize = positionSize;
326 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::MoveResize: %d, %d, %d, %d\n", mPositionSize.x, mPositionSize.y, mPositionSize.width, mPositionSize.height );
329 void WindowRenderSurface::StartRender()
333 bool WindowRenderSurface::PreRender( bool resizingSurface )
335 MakeContextCurrent();
337 if( resizingSurface )
339 int totalAngle = (mRotationAngle + mScreenRotationAngle) % 360;
341 // Window rotate or screen rotate
342 if( !mRotationFinished || !mScreenRotationFinished )
344 mWindowBase->SetEglWindowRotation( totalAngle );
345 mWindowBase->SetEglWindowBufferTransform( totalAngle );
347 // Reset only screen rotation flag
348 mScreenRotationFinished = true;
350 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PreRender: Set rotation [%d] [%d]\n", mRotationAngle, mScreenRotationAngle );
353 // Only window rotate
354 if( !mRotationFinished )
356 mWindowBase->SetEglWindowTransform( mRotationAngle );
360 if ( !mResizeFinished )
362 Dali::PositionSize positionSize;
363 positionSize.x = mPositionSize.x;
364 positionSize.y = mPositionSize.y;
365 if( totalAngle == 0 || totalAngle == 180 )
367 positionSize.width = mPositionSize.width;
368 positionSize.height = mPositionSize.height;
372 positionSize.width = mPositionSize.height;
373 positionSize.height = mPositionSize.width;
376 mWindowBase->ResizeEglWindow( positionSize );
377 mResizeFinished = true;
379 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PreRender: Set resize\n" );
383 auto eglGraphics = static_cast<EglGraphics *>(mGraphics);
386 GlImplementation& mGLES = eglGraphics->GetGlesInterface();
393 void WindowRenderSurface::PostRender( bool renderToFbo, bool replacingSurface, bool resizingSurface )
395 // Inform the gl implementation that rendering has finished before informing the surface
396 auto eglGraphics = static_cast<EglGraphics *>(mGraphics);
399 GlImplementation& mGLES = eglGraphics->GetGlesInterface();
409 if( resizingSurface )
411 if( !mRotationFinished )
413 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PostRender: Trigger rotation event\n" );
415 mRotationTrigger->Trigger();
417 if( mThreadSynchronization )
419 // Wait until the event-thread complete the rotation event processing
420 mThreadSynchronization->PostRenderWaitForCompletion();
426 Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
427 eglImpl.SwapBuffers( mEGLSurface );
429 if( mRenderNotification )
431 mRenderNotification->Trigger();
434 if ( eglImpl.IsSurfacelessContextSupported() )
436 // Switch to the shared context after rendering this surface
437 eglImpl.MakeContextCurrent( EGL_NO_SURFACE, eglImpl.GetContext() );
442 void WindowRenderSurface::StopRender()
446 void WindowRenderSurface::SetThreadSynchronization( ThreadSynchronizationInterface& threadSynchronization )
448 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::SetThreadSynchronization: called\n" );
450 mThreadSynchronization = &threadSynchronization;
453 void WindowRenderSurface::ReleaseLock()
458 Integration::RenderSurface::Type WindowRenderSurface::GetSurfaceType()
460 return RenderSurface::WINDOW_RENDER_SURFACE;
463 void WindowRenderSurface::MakeContextCurrent()
465 if ( mEGL != nullptr )
467 mEGL->MakeContextCurrent( mEGLSurface, mEGLContext );
471 Integration::DepthBufferAvailable WindowRenderSurface::GetDepthBufferRequired()
473 return mGraphics ? mGraphics->GetDepthBufferRequired() : Integration::DepthBufferAvailable::FALSE;
476 Integration::StencilBufferAvailable WindowRenderSurface::GetStencilBufferRequired()
478 return mGraphics ? mGraphics->GetStencilBufferRequired() : Integration::StencilBufferAvailable::FALSE;
481 void WindowRenderSurface::OutputTransformed()
483 int screenRotationAngle = mWindowBase->GetScreenRotationAngle();
485 if( mScreenRotationAngle != screenRotationAngle )
487 mScreenRotationAngle = screenRotationAngle;
488 mScreenRotationFinished = false;
489 mResizeFinished = false;
491 mOutputTransformedSignal.Emit();
493 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::OutputTransformed: angle = %d screen rotation = %d\n", mRotationAngle, mScreenRotationAngle );
497 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::OutputTransformed: Ignore output transform [%d]\n", mScreenRotationAngle );
501 void WindowRenderSurface::ProcessRotationRequest()
503 mRotationFinished = true;
505 mWindowBase->WindowRotationCompleted( mRotationAngle, mPositionSize.width, mPositionSize.height );
507 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::ProcessRotationRequest: Rotation Done\n" );
509 if( mThreadSynchronization )
511 mThreadSynchronization->PostRenderComplete();
515 } // namespace Adaptor
517 } // namespace internal