2 * Copyright (c) 2018 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/gles20/egl-implementation.h>
29 #include <dali/internal/adaptor/common/adaptor-impl.h>
30 #include <dali/internal/window-system/common/window-base.h>
31 #include <dali/internal/window-system/common/window-factory.h>
32 #include <dali/internal/window-system/common/window-system.h>
44 const int MINIMUM_DIMENSION_CHANGE( 1 ); ///< Minimum change for window to be considered to have moved
46 #if defined(DEBUG_ENABLED)
47 Debug::Filter* gWindowRenderSurfaceLogFilter = Debug::Filter::New(Debug::Verbose, false, "LOG_WINDOW_RENDER_SURFACE");
50 } // unnamed namespace
52 WindowRenderSurface::WindowRenderSurface( Dali::PositionSize positionSize, Any surface, bool isTransparent )
53 : mPositionSize( positionSize ),
55 mThreadSynchronization( NULL ),
56 mRenderNotification( NULL ),
57 mRotationTrigger( NULL ),
58 mColorDepth( isTransparent ? COLOR_DEPTH_32 : COLOR_DEPTH_24 ),
59 mOutputTransformedSignal(),
61 mScreenRotationAngle( 0 ),
63 mRotationSupported( false ),
64 mRotationFinished( true ),
65 mScreenRotationFinished( true ),
66 mResizeFinished( true )
68 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "Creating Window\n" );
69 Initialize( surface );
72 WindowRenderSurface::~WindowRenderSurface()
74 if( mRotationTrigger )
76 delete mRotationTrigger;
80 void WindowRenderSurface::Initialize( Any surface )
82 // if width or height are zero, go full screen.
83 if ( (mPositionSize.width == 0) || (mPositionSize.height == 0) )
85 // Default window size == screen size
89 WindowSystem::GetScreenSize( mPositionSize.width, mPositionSize.height );
92 // Create a window base
93 auto windowFactory = Dali::Internal::Adaptor::GetWindowFactory();
94 mWindowBase = windowFactory->CreateWindowBase( mPositionSize, surface, ( mColorDepth == COLOR_DEPTH_32 ? true : false ) );
97 mWindowBase->OutputTransformedSignal().Connect( this, &WindowRenderSurface::OutputTransformed );
99 // Check screen rotation
100 mScreenRotationAngle = mWindowBase->GetScreenRotationAngle();
101 if( mScreenRotationAngle != 0 )
103 mScreenRotationFinished = false;
107 Any WindowRenderSurface::GetNativeWindow()
109 return mWindowBase->GetNativeWindow();
112 int WindowRenderSurface::GetNativeWindowId()
114 return mWindowBase->GetNativeWindowId();
117 void WindowRenderSurface::Map()
122 void WindowRenderSurface::SetRenderNotification( TriggerEventInterface* renderNotification )
124 mRenderNotification = renderNotification;
127 void WindowRenderSurface::SetTransparency( bool transparent )
129 mWindowBase->SetTransparency( transparent );
132 void WindowRenderSurface::RequestRotation( int angle, int width, int height )
134 if( !mRotationSupported )
136 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::Rotate: Rotation is not supported!\n" );
140 if( !mRotationTrigger )
142 TriggerEventFactoryInterface& triggerFactory = Internal::Adaptor::Adaptor::GetImplementation( Adaptor::Get() ).GetTriggerEventFactoryInterface();
143 mRotationTrigger = triggerFactory.CreateTriggerEvent( MakeCallback( this, &WindowRenderSurface::ProcessRotationRequest ), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER );
146 mPositionSize.width = width;
147 mPositionSize.height = height;
149 mRotationAngle = angle;
150 mRotationFinished = false;
152 mWindowBase->SetWindowRotationAngle( mRotationAngle );
154 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::Rotate: angle = %d screen rotation = %d\n", mRotationAngle, mScreenRotationAngle );
157 WindowBase* WindowRenderSurface::GetWindowBase()
159 return mWindowBase.get();
162 WindowBase::OutputSignalType& WindowRenderSurface::OutputTransformedSignal()
164 return mOutputTransformedSignal;
167 PositionSize WindowRenderSurface::GetPositionSize() const
169 return mPositionSize;
172 void WindowRenderSurface::GetDpi( unsigned int& dpiHorizontal, unsigned int& dpiVertical )
174 mWindowBase->GetDpi( dpiHorizontal, dpiVertical );
177 void WindowRenderSurface::InitializeEgl( EglInterface& eglIf )
179 DALI_LOG_TRACE_METHOD( gWindowRenderSurfaceLogFilter );
181 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( eglIf );
183 eglImpl.ChooseConfig(true, mColorDepth);
186 void WindowRenderSurface::CreateEglSurface( EglInterface& eglIf )
188 DALI_LOG_TRACE_METHOD( gWindowRenderSurfaceLogFilter );
191 if( mScreenRotationAngle == 0 || mScreenRotationAngle == 180 )
193 width = mPositionSize.width;
194 height = mPositionSize.height;
198 width = mPositionSize.height;
199 height = mPositionSize.width;
202 // create the EGL window
203 EGLNativeWindowType window = mWindowBase->CreateEglWindow( width, height );
205 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( eglIf );
206 eglImpl.CreateSurfaceWindow( window, mColorDepth );
208 // Check rotation capability
209 mRotationSupported = mWindowBase->IsEglWindowRotationSupported();
211 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::CreateEglSurface: w = %d h = %d angle = %d screen rotation = %d\n", mPositionSize.width, mPositionSize.height, mRotationAngle, mScreenRotationAngle );
214 void WindowRenderSurface::DestroyEglSurface( EglInterface& eglIf )
216 DALI_LOG_TRACE_METHOD( gWindowRenderSurfaceLogFilter );
218 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( eglIf );
219 eglImpl.DestroySurface();
221 mWindowBase->DestroyEglWindow();
224 bool WindowRenderSurface::ReplaceEGLSurface( EglInterface& egl )
226 DALI_LOG_TRACE_METHOD( gWindowRenderSurfaceLogFilter );
228 // Destroy the old one
229 mWindowBase->DestroyEglWindow();
232 if( mScreenRotationAngle == 0 || mScreenRotationAngle == 180 )
234 width = mPositionSize.width;
235 height = mPositionSize.height;
239 width = mPositionSize.height;
240 height = mPositionSize.width;
243 // create the EGL window
244 EGLNativeWindowType window = mWindowBase->CreateEglWindow( width, height );
246 // Set screen rotation
247 mScreenRotationFinished = false;
249 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
250 return eglImpl.ReplaceSurfaceWindow( window );
253 void WindowRenderSurface::MoveResize( Dali::PositionSize positionSize )
255 bool needToMove = false;
256 bool needToResize = false;
259 if( (fabs(positionSize.x - mPositionSize.x) > MINIMUM_DIMENSION_CHANGE) ||
260 (fabs(positionSize.y - mPositionSize.y) > MINIMUM_DIMENSION_CHANGE) )
266 if( (fabs(positionSize.width - mPositionSize.width) > MINIMUM_DIMENSION_CHANGE) ||
267 (fabs(positionSize.height - mPositionSize.height) > MINIMUM_DIMENSION_CHANGE) )
276 mWindowBase->MoveResize( positionSize );
280 mWindowBase->Resize( positionSize );
283 mResizeFinished = false;
284 mPositionSize = positionSize;
290 mWindowBase->Move( positionSize );
292 mPositionSize = positionSize;
296 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::MoveResize: %d, %d, %d, %d\n", mPositionSize.x, mPositionSize.y, mPositionSize.width, mPositionSize.height );
299 void WindowRenderSurface::SetViewMode( ViewMode viewMode )
301 mWindowBase->SetViewMode( viewMode );
304 void WindowRenderSurface::StartRender()
308 bool WindowRenderSurface::PreRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, bool resizingSurface )
310 if( resizingSurface )
312 #ifdef OVER_TIZEN_VERSION_4
313 // Window rotate or screen rotate
314 if( !mRotationFinished || !mScreenRotationFinished )
316 int totalAngle = (mRotationAngle + mScreenRotationAngle) % 360;
318 mWindowBase->SetEglWindowRotation( totalAngle );
319 mWindowBase->SetEglWindowBufferTransform( totalAngle );
321 // Reset only screen rotation flag
322 mScreenRotationFinished = true;
324 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PreRender: Set rotation [%d] [%d]\n", mRotationAngle, mScreenRotationAngle );
327 // Only window rotate
328 if( !mRotationFinished )
330 mWindowBase->SetEglWindowTransform( mRotationAngle );
335 if( !mResizeFinished )
337 mWindowBase->ResizeEglWindow( mPositionSize );
338 mResizeFinished = true;
340 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PreRender: Set resize\n" );
347 void WindowRenderSurface::PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, Dali::DisplayConnection* displayConnection, bool replacingSurface, bool resizingSurface )
349 if( resizingSurface )
351 if( !mRotationFinished )
353 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PostRender: Trigger rotation event\n" );
355 mRotationTrigger->Trigger();
357 if( mThreadSynchronization )
359 // Wait until the event-thread complete the rotation event processing
360 mThreadSynchronization->PostRenderWaitForCompletion();
365 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
366 eglImpl.SwapBuffers();
368 if( mRenderNotification )
370 mRenderNotification->Trigger();
374 void WindowRenderSurface::StopRender()
378 void WindowRenderSurface::SetThreadSynchronization( ThreadSynchronizationInterface& threadSynchronization )
380 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::SetThreadSynchronization: called\n" );
382 mThreadSynchronization = &threadSynchronization;
385 void WindowRenderSurface::ReleaseLock()
390 RenderSurface::Type WindowRenderSurface::GetSurfaceType()
392 return RenderSurface::WINDOW_RENDER_SURFACE;
395 void WindowRenderSurface::OutputTransformed()
397 int screenRotationAngle = mWindowBase->GetScreenRotationAngle();
399 if( mScreenRotationAngle != screenRotationAngle )
401 mScreenRotationAngle = screenRotationAngle;
402 mScreenRotationFinished = false;
404 mOutputTransformedSignal.Emit();
406 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::OutputTransformed: angle = %d screen rotation = %d\n", mRotationAngle, mScreenRotationAngle );
410 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::OutputTransformed: Ignore output transform [%d]\n", mScreenRotationAngle );
414 void WindowRenderSurface::ProcessRotationRequest()
416 mRotationFinished = true;
418 mWindowBase->WindowRotationCompleted( mRotationAngle, mPositionSize.width, mPositionSize.height );
420 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::ProcessRotationRequest: Rotation Done\n" );
422 if( mThreadSynchronization )
424 mThreadSynchronization->PostRenderComplete();
428 } // namespace Adaptor
430 } // namespace internal