2 * Copyright (c) 2017 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 "window-render-surface.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>
34 #include <ecore-x-types.h>
35 #include <trigger-event.h>
36 #include <gl/egl-implementation.h>
37 #include <base/display-connection.h>
42 #if defined(DEBUG_ENABLED)
43 extern Debug::Filter* gRenderSurfaceLogFilter;
52 const int MINIMUM_DIMENSION_CHANGE( 1 ); ///< Minimum change for window to be considered to have moved
54 } // unnamed namespace
56 WindowRenderSurface::WindowRenderSurface( Dali::PositionSize positionSize,
58 const std::string& name,
59 const std::string& className,
61 : EcoreXRenderSurface( positionSize, surface, name, isTransparent ),
63 mNeedToApproveDeiconify(false),
66 DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "Creating Window\n" );
70 WindowRenderSurface::~WindowRenderSurface()
74 ecore_x_window_free( mX11Window );
78 Ecore_X_Drawable WindowRenderSurface::GetDrawable()
80 // already an e-core type
81 return static_cast< Ecore_X_Drawable >( mX11Window );
84 Any WindowRenderSurface::GetSurface()
86 // already an e-core type
87 return Any( mX11Window );
90 Ecore_X_Window WindowRenderSurface::GetXWindow()
95 void WindowRenderSurface::RequestToApproveDeiconify()
97 mNeedToApproveDeiconify = true;
100 void WindowRenderSurface::InitializeEgl( EglInterface& eglIf )
102 DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
104 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( eglIf );
106 eglImpl.ChooseConfig(true, mColorDepth);
109 void WindowRenderSurface::CreateEglSurface( EglInterface& eglIf )
111 DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
113 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( eglIf );
115 // create the EGL surface
116 // need to create X handle as in 64bit system ECore handle is 32 bit whereas EGLnative and XWindow are 64 bit
117 XWindow window( mX11Window );
118 eglImpl.CreateSurfaceWindow( reinterpret_cast< EGLNativeWindowType >( window ), mColorDepth );
121 void WindowRenderSurface::DestroyEglSurface( EglInterface& eglIf )
123 DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
125 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( eglIf );
126 eglImpl.DestroySurface();
129 bool WindowRenderSurface::ReplaceEGLSurface( EglInterface& egl )
131 DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
133 // need to create X handle as in 64bit system ECore handle is 32 bit whereas EGLnative and XWindow are 64 bit
134 XWindow window( mX11Window );
135 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
137 return eglImpl.ReplaceSurfaceWindow( reinterpret_cast< EGLNativeWindowType >( window ) );
140 void WindowRenderSurface::MoveResize( Dali::PositionSize positionSize )
142 bool needToMove = false;
143 bool needToResize = false;
146 if( (fabs(positionSize.x - mPosition.x) > MINIMUM_DIMENSION_CHANGE) ||
147 (fabs(positionSize.y - mPosition.y) > MINIMUM_DIMENSION_CHANGE) )
153 if( (fabs(positionSize.width - mPosition.width) > MINIMUM_DIMENSION_CHANGE) ||
154 (fabs(positionSize.height - mPosition.height) > MINIMUM_DIMENSION_CHANGE) )
159 if( needToMove && needToResize)
161 ecore_x_window_move_resize(mX11Window, positionSize.x, positionSize.y, positionSize.width, positionSize.height);
162 mPosition = positionSize;
166 ecore_x_window_move(mX11Window, positionSize.x, positionSize.y);
167 mPosition = positionSize;
169 else if (needToResize)
171 ecore_x_window_resize(mX11Window, positionSize.width, positionSize.height);
172 mPosition = positionSize;
177 void WindowRenderSurface::Map()
179 ecore_x_window_show(mX11Window);
182 void WindowRenderSurface::StartRender()
186 bool WindowRenderSurface::PreRender( EglInterface&, Integration::GlAbstraction&, bool )
188 // nothing to do for windows
192 void WindowRenderSurface::PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, DisplayConnection* displayConnection, bool replacingSurface, bool resizingSurface )
194 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
195 eglImpl.SwapBuffers();
197 // When the window is deiconified, it approves the deiconify operation to window manager after rendering
198 if(mNeedToApproveDeiconify)
200 // SwapBuffer is desychronized. So make sure to sychronize when window is deiconified.
201 glAbstraction.Finish();
203 XDisplay* display = AnyCast<XDisplay *>(displayConnection->GetDisplay());
205 #ifndef DALI_PROFILE_UBUNTU
206 /* client sends immediately reply message using value 1 */
209 xev.xclient.window = mX11Window;
210 xev.xclient.type = ClientMessage;
211 xev.xclient.message_type = ECORE_X_ATOM_E_DEICONIFY_APPROVE;
212 xev.xclient.format = 32;
213 xev.xclient.data.l[0] = mX11Window;
214 xev.xclient.data.l[1] = 1;
215 xev.xclient.data.l[2] = 0;
216 xev.xclient.data.l[3] = 0;
217 xev.xclient.data.l[4] = 0;
219 XSendEvent(display, mX11Window, false, ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, &xev);
220 #endif // DALI_PROFILE_UBUNTU
222 XSync(display, false);
224 mNeedToApproveDeiconify = false;
228 void WindowRenderSurface::StopRender()
232 void WindowRenderSurface::SetViewMode( ViewMode viewMode )
234 Ecore_X_Atom viewModeAtom( ecore_x_atom_get( "_E_COMP_3D_APP_WIN" ) );
236 if( viewModeAtom != None )
238 unsigned int value( static_cast<unsigned int>( viewMode ) );
239 ecore_x_window_prop_card32_set( mX11Window, viewModeAtom, &value, 1 );
243 void WindowRenderSurface::CreateXRenderable()
245 // if width or height are zero, go full screen.
246 if ( (mPosition.width == 0) || (mPosition.height == 0) )
248 // Default window size == screen size
252 ecore_x_screen_size_get( ecore_x_default_screen_get(), &mPosition.width, &mPosition.height );
255 if(mColorDepth == COLOR_DEPTH_32)
257 // create 32 bit window
258 mX11Window = ecore_x_window_argb_new( 0, mPosition.x, mPosition.y, mPosition.width, mPosition.height );
262 // create 24 bit window
263 mX11Window = ecore_x_window_new( 0, mPosition.x, mPosition.y, mPosition.width, mPosition.height );
266 if ( mX11Window == 0 )
268 DALI_ASSERT_ALWAYS(0 && "Failed to create X window");
271 // set up window title which will be helpful for debug utitilty
272 ecore_x_icccm_title_set( mX11Window, mTitle.c_str() );
273 ecore_x_netwm_name_set( mX11Window, mTitle.c_str() );
274 ecore_x_icccm_name_class_set( mX11Window, mTitle.c_str(), mClassName.c_str() );
276 // set up etc properties to match with ecore-evas
278 if( ( id = getenv("DESKTOP_STARTUP_ID") ) )
280 ecore_x_netwm_startup_id_set( mX11Window, id );
283 ecore_x_icccm_hints_set( mX11Window,
285 ECORE_X_WINDOW_STATE_HINT_NORMAL, // initial_state
292 // we SHOULD guarantee the x11 window was created in x server.
296 void WindowRenderSurface::UseExistingRenderable( unsigned int surfaceId )
298 mX11Window = static_cast< Ecore_X_Window >( surfaceId );
301 void WindowRenderSurface::SetThreadSynchronization( ThreadSynchronizationInterface& /* threadSynchronization */ )
306 void WindowRenderSurface::ReleaseLock()