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/ubuntu-x11/window-render-surface-ecore-x.h>
22 #include <X11/Xatom.h>
24 #include <X11/Xutil.h>
26 #include <X11/extensions/Xfixes.h> // for damage notify
27 #include <X11/extensions/Xdamage.h> // for damage notify
29 #include <dali/integration-api/gl-abstraction.h>
30 #include <dali/integration-api/debug.h>
33 #include <dali/internal/window-system/ubuntu-x11/ecore-x-types.h>
34 #include <dali/internal/system/common/trigger-event.h>
35 #include <dali/internal/graphics/gles20/egl-implementation.h>
36 #include <dali/internal/window-system/common/display-connection.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_ECORE_X");
54 } // unnamed namespace
56 WindowRenderSurfaceEcoreX::WindowRenderSurfaceEcoreX( Dali::PositionSize positionSize,
58 const std::string& name,
59 const std::string& className,
62 mClassName( className ),
63 mPosition( positionSize ),
64 mColorDepth( isTransparent ? COLOR_DEPTH_32 : COLOR_DEPTH_24 ),
67 mNeedToApproveDeiconify( false )
69 DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "Creating Window\n" );
70 Initialize( surface );
73 WindowRenderSurfaceEcoreX::~WindowRenderSurfaceEcoreX()
77 ecore_x_window_free( mX11Window );
81 void WindowRenderSurfaceEcoreX::Initialize( Any surface )
83 // see if there is a surface in Any surface
84 unsigned int surfaceId = GetSurfaceId( surface );
86 // if the surface is empty, create a new one.
89 // we own the surface about to created
95 // XLib should already be initialized so no point in calling XInitThreads
96 UseExistingRenderable( surfaceId );
100 Ecore_X_Window WindowRenderSurfaceEcoreX::GetXWindow()
105 void WindowRenderSurfaceEcoreX::RequestToApproveDeiconify()
107 mNeedToApproveDeiconify = true;
110 Any WindowRenderSurfaceEcoreX::GetWindow()
115 void WindowRenderSurfaceEcoreX::Map()
117 ecore_x_window_show( mX11Window );
120 void WindowRenderSurfaceEcoreX::SetRenderNotification( TriggerEventInterface* renderNotification )
124 void WindowRenderSurfaceEcoreX::SetTransparency( bool transparent )
128 void WindowRenderSurfaceEcoreX::RequestRotation( int angle, int width, int height )
132 PositionSize WindowRenderSurfaceEcoreX::GetPositionSize() const
137 void WindowRenderSurfaceEcoreX::GetDpi( unsigned int& dpiHorizontal, unsigned int& dpiVertical )
142 // 1 inch = 25.4 millimeters
143 xres = ecore_x_dpi_get();
144 yres = ecore_x_dpi_get();
146 dpiHorizontal = int( xres + 0.5f ); // rounding
147 dpiVertical = int( yres + 0.5f );
150 void WindowRenderSurfaceEcoreX::InitializeEgl( EglInterface& eglIf )
152 DALI_LOG_TRACE_METHOD( gWindowRenderSurfaceLogFilter );
154 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( eglIf );
156 eglImpl.ChooseConfig(true, mColorDepth);
159 void WindowRenderSurfaceEcoreX::CreateEglSurface( EglInterface& eglIf )
161 DALI_LOG_TRACE_METHOD( gWindowRenderSurfaceLogFilter );
163 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( eglIf );
165 // create the EGL surface
166 // need to create X handle as in 64bit system ECore handle is 32 bit whereas EGLnative and XWindow are 64 bit
167 XWindow window( mX11Window );
168 eglImpl.CreateSurfaceWindow( reinterpret_cast< EGLNativeWindowType >( window ), mColorDepth );
171 void WindowRenderSurfaceEcoreX::DestroyEglSurface( EglInterface& eglIf )
173 DALI_LOG_TRACE_METHOD( gWindowRenderSurfaceLogFilter );
175 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( eglIf );
176 eglImpl.DestroySurface();
179 bool WindowRenderSurfaceEcoreX::ReplaceEGLSurface( EglInterface& egl )
181 DALI_LOG_TRACE_METHOD( gWindowRenderSurfaceLogFilter );
183 // need to create X handle as in 64bit system ECore handle is 32 bit whereas EGLnative and XWindow are 64 bit
184 XWindow window( mX11Window );
185 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
187 return eglImpl.ReplaceSurfaceWindow( reinterpret_cast< EGLNativeWindowType >( window ) );
190 void WindowRenderSurfaceEcoreX::MoveResize( Dali::PositionSize positionSize )
192 bool needToMove = false;
193 bool needToResize = false;
196 if( (fabs(positionSize.x - mPosition.x) > MINIMUM_DIMENSION_CHANGE) ||
197 (fabs(positionSize.y - mPosition.y) > MINIMUM_DIMENSION_CHANGE) )
203 if( (fabs(positionSize.width - mPosition.width) > MINIMUM_DIMENSION_CHANGE) ||
204 (fabs(positionSize.height - mPosition.height) > MINIMUM_DIMENSION_CHANGE) )
209 if( needToMove && needToResize)
211 ecore_x_window_move_resize(mX11Window, positionSize.x, positionSize.y, positionSize.width, positionSize.height);
212 mPosition = positionSize;
216 ecore_x_window_move(mX11Window, positionSize.x, positionSize.y);
217 mPosition = positionSize;
219 else if (needToResize)
221 ecore_x_window_resize(mX11Window, positionSize.width, positionSize.height);
222 mPosition = positionSize;
226 void WindowRenderSurfaceEcoreX::SetViewMode( ViewMode viewMode )
228 Ecore_X_Atom viewModeAtom( ecore_x_atom_get( "_E_COMP_3D_APP_WIN" ) );
230 if( viewModeAtom != None )
232 unsigned int value( static_cast<unsigned int>( viewMode ) );
233 ecore_x_window_prop_card32_set( mX11Window, viewModeAtom, &value, 1 );
237 void WindowRenderSurfaceEcoreX::StartRender()
241 bool WindowRenderSurfaceEcoreX::PreRender( EglInterface&, Integration::GlAbstraction&, bool )
243 // nothing to do for windows
247 void WindowRenderSurfaceEcoreX::PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, Dali::DisplayConnection* displayConnection, bool replacingSurface, bool resizingSurface )
249 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
250 eglImpl.SwapBuffers();
252 // When the window is deiconified, it approves the deiconify operation to window manager after rendering
253 if(mNeedToApproveDeiconify)
255 // SwapBuffer is desychronized. So make sure to sychronize when window is deiconified.
256 glAbstraction.Finish();
258 XDisplay* display = AnyCast<XDisplay *>(displayConnection->GetDisplay());
260 #ifndef DALI_PROFILE_UBUNTU
261 /* client sends immediately reply message using value 1 */
264 xev.xclient.window = mX11Window;
265 xev.xclient.type = ClientMessage;
266 xev.xclient.message_type = ECORE_X_ATOM_E_DEICONIFY_APPROVE;
267 xev.xclient.format = 32;
268 xev.xclient.data.l[0] = mX11Window;
269 xev.xclient.data.l[1] = 1;
270 xev.xclient.data.l[2] = 0;
271 xev.xclient.data.l[3] = 0;
272 xev.xclient.data.l[4] = 0;
274 XSendEvent(display, mX11Window, false, ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, &xev);
275 #endif // DALI_PROFILE_UBUNTU
277 XSync(display, false);
279 mNeedToApproveDeiconify = false;
283 void WindowRenderSurfaceEcoreX::StopRender()
287 void WindowRenderSurfaceEcoreX::SetThreadSynchronization( ThreadSynchronizationInterface& /* threadSynchronization */ )
292 void WindowRenderSurfaceEcoreX::ReleaseLock()
297 RenderSurface::Type WindowRenderSurfaceEcoreX::GetSurfaceType()
299 return WINDOW_RENDER_SURFACE;
302 void WindowRenderSurfaceEcoreX::CreateRenderable()
304 // if width or height are zero, go full screen.
305 if ( (mPosition.width == 0) || (mPosition.height == 0) )
307 // Default window size == screen size
311 ecore_x_screen_size_get( ecore_x_default_screen_get(), &mPosition.width, &mPosition.height );
314 if(mColorDepth == COLOR_DEPTH_32)
316 // create 32 bit window
317 mX11Window = ecore_x_window_argb_new( 0, mPosition.x, mPosition.y, mPosition.width, mPosition.height );
321 // create 24 bit window
322 mX11Window = ecore_x_window_new( 0, mPosition.x, mPosition.y, mPosition.width, mPosition.height );
325 if ( mX11Window == 0 )
327 DALI_ASSERT_ALWAYS(0 && "Failed to create X window");
330 // set up window title which will be helpful for debug utitilty
331 ecore_x_icccm_title_set( mX11Window, mTitle.c_str() );
332 ecore_x_netwm_name_set( mX11Window, mTitle.c_str() );
333 ecore_x_icccm_name_class_set( mX11Window, mTitle.c_str(), mClassName.c_str() );
335 // set up etc properties to match with ecore-evas
337 if( ( id = getenv("DESKTOP_STARTUP_ID") ) )
339 ecore_x_netwm_startup_id_set( mX11Window, id );
342 ecore_x_icccm_hints_set( mX11Window,
344 ECORE_X_WINDOW_STATE_HINT_NORMAL, // initial_state
351 // we SHOULD guarantee the x11 window was created in x server.
355 void WindowRenderSurfaceEcoreX::UseExistingRenderable( unsigned int surfaceId )
357 mX11Window = static_cast< Ecore_X_Window >( surfaceId );
360 unsigned int WindowRenderSurfaceEcoreX::GetSurfaceId( Any surface ) const
362 unsigned int surfaceId = 0;
364 if ( surface.Empty() == false )
366 // check we have a valid type
367 DALI_ASSERT_ALWAYS( ( (surface.GetType() == typeid (XWindow) ) ||
368 (surface.GetType() == typeid (Ecore_X_Window) ) )
369 && "Surface type is invalid" );
371 if ( surface.GetType() == typeid (Ecore_X_Window) )
373 surfaceId = AnyCast<Ecore_X_Window>( surface );
377 surfaceId = AnyCast<XWindow>( surface );
383 } // namespace Adaptor
385 } // namespace internal