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>
35 #include <dali/internal/system/common/environment-variables.h>
48 const int MINIMUM_DIMENSION_CHANGE( 1 ); ///< Minimum change for window to be considered to have moved
50 #if defined(DEBUG_ENABLED)
51 Debug::Filter* gWindowRenderSurfaceLogFilter = Debug::Filter::New(Debug::Verbose, false, "LOG_WINDOW_RENDER_SURFACE");
54 } // unnamed namespace
56 WindowRenderSurface::WindowRenderSurface( Dali::PositionSize positionSize, Any surface, bool isTransparent )
58 mDisplayConnection( nullptr ),
59 mPositionSize( positionSize ),
61 mThreadSynchronization( NULL ),
62 mRenderNotification( NULL ),
63 mRotationTrigger( NULL ),
65 mEGLSurface( nullptr ),
66 mEGLContext( nullptr ),
67 mColorDepth( isTransparent ? COLOR_DEPTH_32 : COLOR_DEPTH_24 ),
68 mOutputTransformedSignal(),
70 mScreenRotationAngle( 0 ),
72 mRotationSupported( false ),
73 mRotationFinished( true ),
74 mScreenRotationFinished( true ),
75 mResizeFinished( true ),
79 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "Creating Window\n" );
80 Initialize( surface );
83 WindowRenderSurface::~WindowRenderSurface()
85 if( mRotationTrigger )
87 delete mRotationTrigger;
96 void WindowRenderSurface::Initialize( Any surface )
98 // If width or height are zero, go full screen.
99 if ( (mPositionSize.width == 0) || (mPositionSize.height == 0) )
101 // Default window size == screen size
105 WindowSystem::GetScreenSize( mPositionSize.width, mPositionSize.height );
108 // Create a window base
109 auto windowFactory = Dali::Internal::Adaptor::GetWindowFactory();
110 mWindowBase = windowFactory->CreateWindowBase( mPositionSize, surface, ( mColorDepth == COLOR_DEPTH_32 ? true : false ) );
113 mWindowBase->OutputTransformedSignal().Connect( this, &WindowRenderSurface::OutputTransformed );
115 // Check screen rotation
116 mScreenRotationAngle = mWindowBase->GetScreenRotationAngle();
117 if( mScreenRotationAngle != 0 )
119 mScreenRotationFinished = false;
120 mResizeFinished = false;
124 Any WindowRenderSurface::GetNativeWindow()
126 return mWindowBase->GetNativeWindow();
129 int WindowRenderSurface::GetNativeWindowId()
131 return mWindowBase->GetNativeWindowId();
134 void WindowRenderSurface::Map()
139 void WindowRenderSurface::SetRenderNotification( TriggerEventInterface* renderNotification )
141 mRenderNotification = renderNotification;
144 void WindowRenderSurface::SetTransparency( bool transparent )
146 mWindowBase->SetTransparency( transparent );
149 void WindowRenderSurface::RequestRotation( int angle, int width, int height )
151 if( !mRotationTrigger )
153 TriggerEventFactoryInterface& triggerFactory = Internal::Adaptor::Adaptor::GetImplementation( Adaptor::Get() ).GetTriggerEventFactoryInterface();
154 mRotationTrigger = triggerFactory.CreateTriggerEvent( MakeCallback( this, &WindowRenderSurface::ProcessRotationRequest ), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER );
157 mPositionSize.width = width;
158 mPositionSize.height = height;
160 mRotationAngle = angle;
161 mRotationFinished = false;
163 mWindowBase->SetWindowRotationAngle( mRotationAngle );
165 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::Rotate: angle = %d screen rotation = %d\n", mRotationAngle, mScreenRotationAngle );
168 WindowBase* WindowRenderSurface::GetWindowBase()
170 return mWindowBase.get();
173 WindowBase::OutputSignalType& WindowRenderSurface::OutputTransformedSignal()
175 return mOutputTransformedSignal;
178 PositionSize WindowRenderSurface::GetPositionSize() const
180 return mPositionSize;
183 void WindowRenderSurface::GetDpi( unsigned int& dpiHorizontal, unsigned int& dpiVertical )
185 if( mDpiHorizontal == 0 || mDpiVertical == 0 )
187 const char* environmentDpiHorizontal = std::getenv( DALI_ENV_DPI_HORIZONTAL );
188 mDpiHorizontal = environmentDpiHorizontal ? std::atoi( environmentDpiHorizontal ) : 0;
190 const char* environmentDpiVertical = std::getenv( DALI_ENV_DPI_VERTICAL );
191 mDpiVertical = environmentDpiVertical ? std::atoi( environmentDpiVertical ) : 0;
193 if( mDpiHorizontal == 0 || mDpiVertical == 0 )
195 mWindowBase->GetDpi( mDpiHorizontal, mDpiVertical );
199 dpiHorizontal = mDpiHorizontal;
200 dpiVertical = mDpiVertical;
203 int WindowRenderSurface::GetOrientation() const
205 return mWindowBase->GetOrientation();
208 void WindowRenderSurface::InitializeGraphics()
211 mGraphics = &mAdaptor->GetGraphicsInterface();
213 auto eglGraphics = static_cast<EglGraphics *>(mGraphics);
214 mEGL = &eglGraphics->GetEglInterface();
216 if ( mEGLContext == NULL )
218 // Create the OpenGL context for this window
219 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>(*mEGL);
220 eglImpl.ChooseConfig(true, mColorDepth);
221 eglImpl.CreateWindowContext( mEGLContext );
223 // Create the OpenGL surface
228 void WindowRenderSurface::CreateSurface()
230 DALI_LOG_TRACE_METHOD( gWindowRenderSurfaceLogFilter );
233 if( mScreenRotationAngle == 0 || mScreenRotationAngle == 180 )
235 width = mPositionSize.width;
236 height = mPositionSize.height;
240 width = mPositionSize.height;
241 height = mPositionSize.width;
244 // Create the EGL window
245 EGLNativeWindowType window = mWindowBase->CreateEglWindow( width, height );
247 auto eglGraphics = static_cast<EglGraphics *>(mGraphics);
249 Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
250 mEGLSurface = eglImpl.CreateSurfaceWindow( window, mColorDepth );
252 // Check rotation capability
253 mRotationSupported = mWindowBase->IsEglWindowRotationSupported();
255 int screenWidth, screenHeight;
256 WindowSystem::GetScreenSize( screenWidth, screenHeight );
257 DALI_LOG_RELEASE_INFO("WindowRenderSurface::CreateSurface: w = %d h = %d screenWidth = %d screenHeight = %d angle = %d screen rotation = %d\n",
258 mPositionSize.width, mPositionSize.height, screenWidth, screenHeight, mRotationAngle, mScreenRotationAngle );
261 void WindowRenderSurface::DestroySurface()
263 DALI_LOG_TRACE_METHOD( gWindowRenderSurfaceLogFilter );
265 auto eglGraphics = static_cast<EglGraphics *>(mGraphics);
267 Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
268 eglImpl.DestroySurface( mEGLSurface );
270 mWindowBase->DestroyEglWindow();
273 bool WindowRenderSurface::ReplaceGraphicsSurface()
275 DALI_LOG_TRACE_METHOD( gWindowRenderSurfaceLogFilter );
277 // Destroy the old one
278 mWindowBase->DestroyEglWindow();
281 if( mScreenRotationAngle == 0 || mScreenRotationAngle == 180 )
283 width = mPositionSize.width;
284 height = mPositionSize.height;
288 width = mPositionSize.height;
289 height = mPositionSize.width;
292 // Create the EGL window
293 EGLNativeWindowType window = mWindowBase->CreateEglWindow( width, height );
295 // Set screen rotation
296 mScreenRotationFinished = false;
298 auto eglGraphics = static_cast<EglGraphics *>(mGraphics);
300 Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
301 return eglImpl.ReplaceSurfaceWindow( window, mEGLSurface, mEGLContext );
304 void WindowRenderSurface::MoveResize( Dali::PositionSize positionSize )
306 bool needToMove = false;
307 bool needToResize = false;
310 if( (fabs(positionSize.x - mPositionSize.x) > MINIMUM_DIMENSION_CHANGE) ||
311 (fabs(positionSize.y - mPositionSize.y) > MINIMUM_DIMENSION_CHANGE) )
317 if( (fabs(positionSize.width - mPositionSize.width) > MINIMUM_DIMENSION_CHANGE) ||
318 (fabs(positionSize.height - mPositionSize.height) > MINIMUM_DIMENSION_CHANGE) )
327 mWindowBase->MoveResize( positionSize );
331 mWindowBase->Resize( positionSize );
334 mResizeFinished = false;
335 mPositionSize = positionSize;
341 mWindowBase->Move( positionSize );
343 mPositionSize = positionSize;
347 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::MoveResize: %d, %d, %d, %d\n", mPositionSize.x, mPositionSize.y, mPositionSize.width, mPositionSize.height );
350 void WindowRenderSurface::StartRender()
354 bool WindowRenderSurface::PreRender( bool resizingSurface )
356 MakeContextCurrent();
358 if( resizingSurface )
360 int totalAngle = (mRotationAngle + mScreenRotationAngle) % 360;
362 // Window rotate or screen rotate
363 if( !mRotationFinished || !mScreenRotationFinished )
365 mWindowBase->SetEglWindowRotation( totalAngle );
366 mWindowBase->SetEglWindowBufferTransform( totalAngle );
368 // Reset only screen rotation flag
369 mScreenRotationFinished = true;
371 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PreRender: Set rotation [%d] [%d]\n", mRotationAngle, mScreenRotationAngle );
374 // Only window rotate
375 if( !mRotationFinished )
377 mWindowBase->SetEglWindowTransform( mRotationAngle );
381 if ( !mResizeFinished )
383 Dali::PositionSize positionSize;
384 positionSize.x = mPositionSize.x;
385 positionSize.y = mPositionSize.y;
386 if( totalAngle == 0 || totalAngle == 180 )
388 positionSize.width = mPositionSize.width;
389 positionSize.height = mPositionSize.height;
393 positionSize.width = mPositionSize.height;
394 positionSize.height = mPositionSize.width;
397 mWindowBase->ResizeEglWindow( positionSize );
398 mResizeFinished = true;
400 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PreRender: Set resize\n" );
404 auto eglGraphics = static_cast<EglGraphics *>(mGraphics);
407 GlImplementation& mGLES = eglGraphics->GetGlesInterface();
414 void WindowRenderSurface::PostRender( bool renderToFbo, bool replacingSurface, bool resizingSurface )
416 // Inform the gl implementation that rendering has finished before informing the surface
417 auto eglGraphics = static_cast<EglGraphics *>(mGraphics);
420 GlImplementation& mGLES = eglGraphics->GetGlesInterface();
430 if( resizingSurface )
432 if( !mRotationFinished )
434 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PostRender: Trigger rotation event\n" );
436 mRotationTrigger->Trigger();
438 if( mThreadSynchronization )
440 // Wait until the event-thread complete the rotation event processing
441 mThreadSynchronization->PostRenderWaitForCompletion();
447 Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
448 eglImpl.SwapBuffers( mEGLSurface );
450 if( mRenderNotification )
452 mRenderNotification->Trigger();
457 void WindowRenderSurface::StopRender()
461 void WindowRenderSurface::SetThreadSynchronization( ThreadSynchronizationInterface& threadSynchronization )
463 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::SetThreadSynchronization: called\n" );
465 mThreadSynchronization = &threadSynchronization;
468 void WindowRenderSurface::ReleaseLock()
473 Integration::RenderSurface::Type WindowRenderSurface::GetSurfaceType()
475 return RenderSurface::WINDOW_RENDER_SURFACE;
478 void WindowRenderSurface::MakeContextCurrent()
480 if ( mEGL != nullptr )
482 mEGL->MakeContextCurrent( mEGLSurface, mEGLContext );
486 Integration::DepthBufferAvailable WindowRenderSurface::GetDepthBufferRequired()
488 return mGraphics ? mGraphics->GetDepthBufferRequired() : Integration::DepthBufferAvailable::FALSE;
491 Integration::StencilBufferAvailable WindowRenderSurface::GetStencilBufferRequired()
493 return mGraphics ? mGraphics->GetStencilBufferRequired() : Integration::StencilBufferAvailable::FALSE;
496 void WindowRenderSurface::OutputTransformed()
498 int screenRotationAngle = mWindowBase->GetScreenRotationAngle();
500 if( mScreenRotationAngle != screenRotationAngle )
502 mScreenRotationAngle = screenRotationAngle;
503 mScreenRotationFinished = false;
504 mResizeFinished = false;
506 mOutputTransformedSignal.Emit();
508 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::OutputTransformed: angle = %d screen rotation = %d\n", mRotationAngle, mScreenRotationAngle );
512 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::OutputTransformed: Ignore output transform [%d]\n", mScreenRotationAngle );
516 void WindowRenderSurface::ProcessRotationRequest()
518 mRotationFinished = true;
520 mWindowBase->WindowRotationCompleted( mRotationAngle, mPositionSize.width, mPositionSize.height );
522 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::ProcessRotationRequest: Rotation Done\n" );
524 if( mThreadSynchronization )
526 mThreadSynchronization->PostRenderComplete();
530 } // namespace Adaptor
532 } // namespace internal