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/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 )
56 : mPositionSize( positionSize ),
58 mThreadSynchronization( NULL ),
59 mRenderNotification( NULL ),
60 mRotationTrigger( NULL ),
62 mEGLSurface( nullptr ),
63 mEGLContext( nullptr ),
64 mColorDepth( isTransparent ? COLOR_DEPTH_32 : COLOR_DEPTH_24 ),
65 mOutputTransformedSignal(),
67 mScreenRotationAngle( 0 ),
69 mRotationSupported( false ),
70 mRotationFinished( true ),
71 mScreenRotationFinished( true ),
72 mResizeFinished( true )
74 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "Creating Window\n" );
75 Initialize( surface );
78 WindowRenderSurface::~WindowRenderSurface()
80 if( mRotationTrigger )
82 delete mRotationTrigger;
86 void WindowRenderSurface::Initialize( Any surface )
88 // If width or height are zero, go full screen.
89 if ( (mPositionSize.width == 0) || (mPositionSize.height == 0) )
91 // Default window size == screen size
95 WindowSystem::GetScreenSize( mPositionSize.width, mPositionSize.height );
98 // Create a window base
99 auto windowFactory = Dali::Internal::Adaptor::GetWindowFactory();
100 mWindowBase = windowFactory->CreateWindowBase( mPositionSize, surface, ( mColorDepth == COLOR_DEPTH_32 ? true : false ) );
103 mWindowBase->OutputTransformedSignal().Connect( this, &WindowRenderSurface::OutputTransformed );
105 // Check screen rotation
106 mScreenRotationAngle = mWindowBase->GetScreenRotationAngle();
107 if( mScreenRotationAngle != 0 )
109 mScreenRotationFinished = false;
113 Any WindowRenderSurface::GetNativeWindow()
115 return mWindowBase->GetNativeWindow();
118 int WindowRenderSurface::GetNativeWindowId()
120 return mWindowBase->GetNativeWindowId();
123 void WindowRenderSurface::Map()
128 void WindowRenderSurface::SetRenderNotification( TriggerEventInterface* renderNotification )
130 mRenderNotification = renderNotification;
133 void WindowRenderSurface::SetTransparency( bool transparent )
135 mWindowBase->SetTransparency( transparent );
138 void WindowRenderSurface::RequestRotation( int angle, int width, int height )
140 if( !mRotationSupported )
142 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::Rotate: Rotation is not supported!\n" );
146 if( !mRotationTrigger )
148 TriggerEventFactoryInterface& triggerFactory = Internal::Adaptor::Adaptor::GetImplementation( Adaptor::Get() ).GetTriggerEventFactoryInterface();
149 mRotationTrigger = triggerFactory.CreateTriggerEvent( MakeCallback( this, &WindowRenderSurface::ProcessRotationRequest ), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER );
152 mPositionSize.width = width;
153 mPositionSize.height = height;
155 mRotationAngle = angle;
156 mRotationFinished = false;
158 mWindowBase->SetWindowRotationAngle( mRotationAngle );
160 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::Rotate: angle = %d screen rotation = %d\n", mRotationAngle, mScreenRotationAngle );
163 WindowBase* WindowRenderSurface::GetWindowBase()
165 return mWindowBase.get();
168 WindowBase::OutputSignalType& WindowRenderSurface::OutputTransformedSignal()
170 return mOutputTransformedSignal;
173 PositionSize WindowRenderSurface::GetPositionSize() const
175 return mPositionSize;
178 void WindowRenderSurface::GetDpi( unsigned int& dpiHorizontal, unsigned int& dpiVertical )
180 mWindowBase->GetDpi( dpiHorizontal, dpiVertical );
183 void WindowRenderSurface::InitializeGraphics()
186 mGraphics = &mAdaptor->GetGraphicsInterface();
188 auto eglGraphics = static_cast<EglGraphics *>(mGraphics);
189 mEGL = &eglGraphics->GetEglInterface();
191 if ( mEGLContext == NULL )
193 // Create the OpenGL context for this window
194 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>(*mEGL);
195 eglImpl.ChooseConfig(true, mColorDepth);
196 eglImpl.CreateWindowContext( mEGLContext );
198 // Create the OpenGL surface
203 void WindowRenderSurface::CreateSurface()
205 DALI_LOG_TRACE_METHOD( gWindowRenderSurfaceLogFilter );
208 if( mScreenRotationAngle == 0 || mScreenRotationAngle == 180 )
210 width = mPositionSize.width;
211 height = mPositionSize.height;
215 width = mPositionSize.height;
216 height = mPositionSize.width;
219 // Create the EGL window
220 EGLNativeWindowType window = mWindowBase->CreateEglWindow( width, height );
222 auto eglGraphics = static_cast<EglGraphics *>(mGraphics);
224 Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
225 mEGLSurface = eglImpl.CreateSurfaceWindow( window, mColorDepth );
227 // Check rotation capability
228 mRotationSupported = mWindowBase->IsEglWindowRotationSupported();
230 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::CreateSurface: w = %d h = %d angle = %d screen rotation = %d\n", mPositionSize.width, mPositionSize.height, mRotationAngle, mScreenRotationAngle );
233 void WindowRenderSurface::DestroySurface()
235 DALI_LOG_TRACE_METHOD( gWindowRenderSurfaceLogFilter );
237 auto eglGraphics = static_cast<EglGraphics *>(mGraphics);
239 Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
240 eglImpl.DestroySurface( mEGLSurface );
242 mWindowBase->DestroyEglWindow();
245 bool WindowRenderSurface::ReplaceGraphicsSurface()
247 DALI_LOG_TRACE_METHOD( gWindowRenderSurfaceLogFilter );
249 // Destroy the old one
250 mWindowBase->DestroyEglWindow();
253 if( mScreenRotationAngle == 0 || mScreenRotationAngle == 180 )
255 width = mPositionSize.width;
256 height = mPositionSize.height;
260 width = mPositionSize.height;
261 height = mPositionSize.width;
264 // Create the EGL window
265 EGLNativeWindowType window = mWindowBase->CreateEglWindow( width, height );
267 // Set screen rotation
268 mScreenRotationFinished = false;
270 auto eglGraphics = static_cast<EglGraphics *>(mGraphics);
272 Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
273 return eglImpl.ReplaceSurfaceWindow( window, mEGLSurface, mEGLContext );
276 void WindowRenderSurface::MoveResize( Dali::PositionSize positionSize )
278 bool needToMove = false;
279 bool needToResize = false;
282 if( (fabs(positionSize.x - mPositionSize.x) > MINIMUM_DIMENSION_CHANGE) ||
283 (fabs(positionSize.y - mPositionSize.y) > MINIMUM_DIMENSION_CHANGE) )
289 if( (fabs(positionSize.width - mPositionSize.width) > MINIMUM_DIMENSION_CHANGE) ||
290 (fabs(positionSize.height - mPositionSize.height) > MINIMUM_DIMENSION_CHANGE) )
299 mWindowBase->MoveResize( positionSize );
303 mWindowBase->Resize( positionSize );
306 mResizeFinished = false;
307 mPositionSize = positionSize;
313 mWindowBase->Move( positionSize );
315 mPositionSize = positionSize;
319 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::MoveResize: %d, %d, %d, %d\n", mPositionSize.x, mPositionSize.y, mPositionSize.width, mPositionSize.height );
322 void WindowRenderSurface::StartRender()
326 bool WindowRenderSurface::PreRender( bool resizingSurface )
328 MakeContextCurrent();
330 if( resizingSurface )
332 #ifdef OVER_TIZEN_VERSION_4
333 // Window rotate or screen rotate
334 if( !mRotationFinished || !mScreenRotationFinished )
336 int totalAngle = (mRotationAngle + mScreenRotationAngle) % 360;
338 mWindowBase->SetEglWindowRotation( totalAngle );
339 mWindowBase->SetEglWindowBufferTransform( totalAngle );
341 // Reset only screen rotation flag
342 mScreenRotationFinished = true;
344 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PreRender: Set rotation [%d] [%d]\n", mRotationAngle, mScreenRotationAngle );
347 // Only window rotate
348 if( !mRotationFinished )
350 mWindowBase->SetEglWindowTransform( mRotationAngle );
355 if( !mResizeFinished )
357 mWindowBase->ResizeEglWindow( mPositionSize );
358 mResizeFinished = true;
360 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PreRender: Set resize\n" );
364 auto eglGraphics = static_cast<EglGraphics *>(mGraphics);
367 GlImplementation& mGLES = eglGraphics->GetGlesInterface();
374 void WindowRenderSurface::PostRender( bool renderToFbo, bool replacingSurface, bool resizingSurface )
376 // Inform the gl implementation that rendering has finished before informing the surface
377 auto eglGraphics = static_cast<EglGraphics *>(mGraphics);
380 GlImplementation& mGLES = eglGraphics->GetGlesInterface();
390 if( resizingSurface )
392 if( !mRotationFinished )
394 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PostRender: Trigger rotation event\n" );
396 mRotationTrigger->Trigger();
398 if( mThreadSynchronization )
400 // Wait until the event-thread complete the rotation event processing
401 mThreadSynchronization->PostRenderWaitForCompletion();
407 Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
408 eglImpl.SwapBuffers( mEGLSurface );
410 if( mRenderNotification )
412 mRenderNotification->Trigger();
417 void WindowRenderSurface::StopRender()
421 void WindowRenderSurface::SetThreadSynchronization( ThreadSynchronizationInterface& threadSynchronization )
423 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::SetThreadSynchronization: called\n" );
425 mThreadSynchronization = &threadSynchronization;
428 void WindowRenderSurface::ReleaseLock()
433 Integration::RenderSurface::Type WindowRenderSurface::GetSurfaceType()
435 return RenderSurface::WINDOW_RENDER_SURFACE;
438 void WindowRenderSurface::MakeContextCurrent()
440 if ( mEGL != nullptr )
442 mEGL->MakeContextCurrent( mEGLSurface, mEGLContext );
446 Integration::DepthBufferAvailable WindowRenderSurface::GetDepthBufferRequired()
448 return mGraphics ? mGraphics->GetDepthBufferRequired() : Integration::DepthBufferAvailable::FALSE;
451 Integration::StencilBufferAvailable WindowRenderSurface::GetStencilBufferRequired()
453 return mGraphics ? mGraphics->GetStencilBufferRequired() : Integration::StencilBufferAvailable::FALSE;
456 void WindowRenderSurface::OutputTransformed()
458 int screenRotationAngle = mWindowBase->GetScreenRotationAngle();
460 if( mScreenRotationAngle != screenRotationAngle )
462 mScreenRotationAngle = screenRotationAngle;
463 mScreenRotationFinished = false;
465 mOutputTransformedSignal.Emit();
467 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::OutputTransformed: angle = %d screen rotation = %d\n", mRotationAngle, mScreenRotationAngle );
471 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::OutputTransformed: Ignore output transform [%d]\n", mScreenRotationAngle );
475 void WindowRenderSurface::ProcessRotationRequest()
477 mRotationFinished = true;
479 mWindowBase->WindowRotationCompleted( mRotationAngle, mPositionSize.width, mPositionSize.height );
481 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::ProcessRotationRequest: Rotation Done\n" );
483 if( mThreadSynchronization )
485 mThreadSynchronization->PostRenderComplete();
489 } // namespace Adaptor
491 } // namespace internal