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/gles/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>
33 #include <dali/internal/graphics/gles/egl-graphics.h>
46 const int MINIMUM_DIMENSION_CHANGE( 1 ); ///< Minimum change for window to be considered to have moved
48 #if defined(DEBUG_ENABLED)
49 Debug::Filter* gWindowRenderSurfaceLogFilter = Debug::Filter::New(Debug::Verbose, false, "LOG_WINDOW_RENDER_SURFACE");
52 } // unnamed namespace
54 WindowRenderSurface::WindowRenderSurface( Dali::PositionSize positionSize, Any surface, bool isTransparent )
55 : mPositionSize( positionSize ),
57 mThreadSynchronization( NULL ),
58 mRenderNotification( NULL ),
59 mRotationTrigger( NULL ),
61 mColorDepth( isTransparent ? COLOR_DEPTH_32 : COLOR_DEPTH_24 ),
62 mOutputTransformedSignal(),
64 mScreenRotationAngle( 0 ),
66 mRotationSupported( false ),
67 mRotationFinished( true ),
68 mScreenRotationFinished( true ),
69 mResizeFinished( true )
71 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "Creating Window\n" );
72 Initialize( surface );
75 WindowRenderSurface::~WindowRenderSurface()
77 if( mRotationTrigger )
79 delete mRotationTrigger;
83 void WindowRenderSurface::Initialize( Any surface )
85 // If width or height are zero, go full screen.
86 if ( (mPositionSize.width == 0) || (mPositionSize.height == 0) )
88 // Default window size == screen size
92 WindowSystem::GetScreenSize( mPositionSize.width, mPositionSize.height );
95 // Create a window base
96 auto windowFactory = Dali::Internal::Adaptor::GetWindowFactory();
97 mWindowBase = windowFactory->CreateWindowBase( mPositionSize, surface, ( mColorDepth == COLOR_DEPTH_32 ? true : false ) );
100 mWindowBase->OutputTransformedSignal().Connect( this, &WindowRenderSurface::OutputTransformed );
102 // Check screen rotation
103 mScreenRotationAngle = mWindowBase->GetScreenRotationAngle();
104 if( mScreenRotationAngle != 0 )
106 mScreenRotationFinished = false;
110 Any WindowRenderSurface::GetNativeWindow()
112 return mWindowBase->GetNativeWindow();
115 int WindowRenderSurface::GetNativeWindowId()
117 return mWindowBase->GetNativeWindowId();
120 void WindowRenderSurface::Map()
125 void WindowRenderSurface::SetRenderNotification( TriggerEventInterface* renderNotification )
127 mRenderNotification = renderNotification;
130 void WindowRenderSurface::SetTransparency( bool transparent )
132 mWindowBase->SetTransparency( transparent );
135 void WindowRenderSurface::RequestRotation( int angle, int width, int height )
137 if( !mRotationSupported )
139 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::Rotate: Rotation is not supported!\n" );
143 if( !mRotationTrigger )
145 TriggerEventFactoryInterface& triggerFactory = Internal::Adaptor::Adaptor::GetImplementation( Adaptor::Get() ).GetTriggerEventFactoryInterface();
146 mRotationTrigger = triggerFactory.CreateTriggerEvent( MakeCallback( this, &WindowRenderSurface::ProcessRotationRequest ), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER );
149 mPositionSize.width = width;
150 mPositionSize.height = height;
152 mRotationAngle = angle;
153 mRotationFinished = false;
155 mWindowBase->SetWindowRotationAngle( mRotationAngle );
157 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::Rotate: angle = %d screen rotation = %d\n", mRotationAngle, mScreenRotationAngle );
160 WindowBase* WindowRenderSurface::GetWindowBase()
162 return mWindowBase.get();
165 WindowBase::OutputSignalType& WindowRenderSurface::OutputTransformedSignal()
167 return mOutputTransformedSignal;
170 PositionSize WindowRenderSurface::GetPositionSize() const
172 return mPositionSize;
175 void WindowRenderSurface::GetDpi( unsigned int& dpiHorizontal, unsigned int& dpiVertical )
177 mWindowBase->GetDpi( dpiHorizontal, dpiVertical );
180 void WindowRenderSurface::InitializeGraphics( GraphicsInterface& graphics, Dali::DisplayConnection& displayConnection )
182 mGraphics = &graphics;
184 auto eglGraphics = static_cast<EglGraphics *>(mGraphics);
186 EglInterface* mEGL = eglGraphics->Create();
188 // Initialize EGL & OpenGL
189 displayConnection.Initialize();
191 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>(*mEGL);
192 eglImpl.ChooseConfig(true, mColorDepth);
194 // Create the OpenGL context
195 mEGL->CreateContext();
197 // Create the OpenGL surface
201 mEGL->MakeContextCurrent();
204 void WindowRenderSurface::CreateSurface()
206 DALI_LOG_TRACE_METHOD( gWindowRenderSurfaceLogFilter );
209 if( mScreenRotationAngle == 0 || mScreenRotationAngle == 180 )
211 width = mPositionSize.width;
212 height = mPositionSize.height;
216 width = mPositionSize.height;
217 height = mPositionSize.width;
220 // Create the EGL window
221 EGLNativeWindowType window = mWindowBase->CreateEglWindow( width, height );
223 auto eglGraphics = static_cast<EglGraphics *>(mGraphics);
225 Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
226 eglImpl.CreateSurfaceWindow( window, mColorDepth );
228 // Check rotation capability
229 mRotationSupported = mWindowBase->IsEglWindowRotationSupported();
231 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::CreateSurface: w = %d h = %d angle = %d screen rotation = %d\n", mPositionSize.width, mPositionSize.height, mRotationAngle, mScreenRotationAngle );
234 void WindowRenderSurface::DestroySurface()
236 DALI_LOG_TRACE_METHOD( gWindowRenderSurfaceLogFilter );
238 auto eglGraphics = static_cast<EglGraphics *>(mGraphics);
240 Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
241 eglImpl.DestroySurface();
243 mWindowBase->DestroyEglWindow();
246 bool WindowRenderSurface::ReplaceGraphicsSurface()
248 DALI_LOG_TRACE_METHOD( gWindowRenderSurfaceLogFilter );
250 // Destroy the old one
251 mWindowBase->DestroyEglWindow();
254 if( mScreenRotationAngle == 0 || mScreenRotationAngle == 180 )
256 width = mPositionSize.width;
257 height = mPositionSize.height;
261 width = mPositionSize.height;
262 height = mPositionSize.width;
265 // Create the EGL window
266 EGLNativeWindowType window = mWindowBase->CreateEglWindow( width, height );
268 // Set screen rotation
269 mScreenRotationFinished = false;
271 auto eglGraphics = static_cast<EglGraphics *>(mGraphics);
273 Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
274 return eglImpl.ReplaceSurfaceWindow( window );
277 void WindowRenderSurface::MoveResize( Dali::PositionSize positionSize )
279 bool needToMove = false;
280 bool needToResize = false;
283 if( (fabs(positionSize.x - mPositionSize.x) > MINIMUM_DIMENSION_CHANGE) ||
284 (fabs(positionSize.y - mPositionSize.y) > MINIMUM_DIMENSION_CHANGE) )
290 if( (fabs(positionSize.width - mPositionSize.width) > MINIMUM_DIMENSION_CHANGE) ||
291 (fabs(positionSize.height - mPositionSize.height) > MINIMUM_DIMENSION_CHANGE) )
300 mWindowBase->MoveResize( positionSize );
304 mWindowBase->Resize( positionSize );
307 mResizeFinished = false;
308 mPositionSize = positionSize;
314 mWindowBase->Move( positionSize );
316 mPositionSize = positionSize;
320 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::MoveResize: %d, %d, %d, %d\n", mPositionSize.x, mPositionSize.y, mPositionSize.width, mPositionSize.height );
323 void WindowRenderSurface::StartRender()
327 bool WindowRenderSurface::PreRender( bool resizingSurface )
329 if( resizingSurface )
331 #ifdef OVER_TIZEN_VERSION_4
332 // Window rotate or screen rotate
333 if( !mRotationFinished || !mScreenRotationFinished )
335 int totalAngle = (mRotationAngle + mScreenRotationAngle) % 360;
337 mWindowBase->SetEglWindowRotation( totalAngle );
338 mWindowBase->SetEglWindowBufferTransform( totalAngle );
340 // Reset only screen rotation flag
341 mScreenRotationFinished = true;
343 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PreRender: Set rotation [%d] [%d]\n", mRotationAngle, mScreenRotationAngle );
346 // Only window rotate
347 if( !mRotationFinished )
349 mWindowBase->SetEglWindowTransform( mRotationAngle );
354 if( !mResizeFinished )
356 mWindowBase->ResizeEglWindow( mPositionSize );
357 mResizeFinished = true;
359 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PreRender: Set resize\n" );
363 auto eglGraphics = static_cast<EglGraphics *>(mGraphics);
364 auto mGLES = eglGraphics->GetGlesInterface();
370 void WindowRenderSurface::PostRender( bool renderToFbo, bool replacingSurface, bool resizingSurface )
372 // Inform the gl implementation that rendering has finished before informing the surface
373 auto eglGraphics = static_cast<EglGraphics *>(mGraphics);
374 auto mGLES = eglGraphics->GetGlesInterface();
384 if( resizingSurface )
386 if( !mRotationFinished )
388 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PostRender: Trigger rotation event\n" );
390 mRotationTrigger->Trigger();
392 if( mThreadSynchronization )
394 // Wait until the event-thread complete the rotation event processing
395 mThreadSynchronization->PostRenderWaitForCompletion();
401 Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
402 eglImpl.SwapBuffers();
404 if( mRenderNotification )
406 mRenderNotification->Trigger();
410 void WindowRenderSurface::StopRender()
414 void WindowRenderSurface::SetThreadSynchronization( ThreadSynchronizationInterface& threadSynchronization )
416 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::SetThreadSynchronization: called\n" );
418 mThreadSynchronization = &threadSynchronization;
421 void WindowRenderSurface::ReleaseLock()
426 RenderSurface::Type WindowRenderSurface::GetSurfaceType()
428 return RenderSurface::WINDOW_RENDER_SURFACE;
431 void WindowRenderSurface::OutputTransformed()
433 int screenRotationAngle = mWindowBase->GetScreenRotationAngle();
435 if( mScreenRotationAngle != screenRotationAngle )
437 mScreenRotationAngle = screenRotationAngle;
438 mScreenRotationFinished = false;
440 mOutputTransformedSignal.Emit();
442 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::OutputTransformed: angle = %d screen rotation = %d\n", mRotationAngle, mScreenRotationAngle );
446 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::OutputTransformed: Ignore output transform [%d]\n", mScreenRotationAngle );
450 void WindowRenderSurface::ProcessRotationRequest()
452 mRotationFinished = true;
454 mWindowBase->WindowRotationCompleted( mRotationAngle, mPositionSize.width, mPositionSize.height );
456 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::ProcessRotationRequest: Rotation Done\n" );
458 if( mThreadSynchronization )
460 mThreadSynchronization->PostRenderComplete();
464 } // namespace Adaptor
466 } // namespace internal