2 * Copyright (c) 2014 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 ),
62 mNeedToApproveDeiconify(false),
65 DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "Creating Window\n" );
69 WindowRenderSurface::~WindowRenderSurface()
73 ecore_x_window_free( mX11Window );
77 Ecore_X_Drawable WindowRenderSurface::GetDrawable()
79 // already an e-core type
80 return (Ecore_X_Drawable)mX11Window;
83 Any WindowRenderSurface::GetSurface()
85 // already an e-core type
86 return Any( mX11Window );
89 Ecore_X_Window WindowRenderSurface::GetXWindow()
94 void WindowRenderSurface::RequestToApproveDeiconify()
96 mNeedToApproveDeiconify = true;
99 void WindowRenderSurface::InitializeEgl( EglInterface& eglIf )
101 DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
103 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( eglIf );
105 eglImpl.ChooseConfig(true, mColorDepth);
108 void WindowRenderSurface::CreateEglSurface( EglInterface& eglIf )
110 DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
112 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( eglIf );
114 // create the EGL surface
115 // need to cast to X handle as in 64bit system ECore handle is 32 bit whereas EGLnative and XWindow are 64 bit
116 XWindow window = static_cast< XWindow>( mX11Window );
117 eglImpl.CreateSurfaceWindow( (EGLNativeWindowType)window, mColorDepth ); // reinterpret_cast does not compile
120 void WindowRenderSurface::DestroyEglSurface( EglInterface& eglIf )
122 DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
124 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( eglIf );
125 eglImpl.DestroySurface();
128 bool WindowRenderSurface::ReplaceEGLSurface( EglInterface& egl )
130 DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
132 // need to cast to X handle as in 64bit system ECore handle is 32 bit whereas EGLnative and XWindow are 64 bit
133 XWindow window = static_cast< XWindow >( mX11Window );
134 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
136 return eglImpl.ReplaceSurfaceWindow( (EGLNativeWindowType)window ); // reinterpret_cast does not compile
139 void WindowRenderSurface::MoveResize( Dali::PositionSize positionSize )
141 bool needToMove = false;
142 bool needToResize = false;
145 if( (fabs(positionSize.x - mPosition.x) > MINIMUM_DIMENSION_CHANGE) ||
146 (fabs(positionSize.y - mPosition.y) > MINIMUM_DIMENSION_CHANGE) )
152 if( (fabs(positionSize.width - mPosition.width) > MINIMUM_DIMENSION_CHANGE) ||
153 (fabs(positionSize.height - mPosition.height) > MINIMUM_DIMENSION_CHANGE) )
158 if( needToMove && needToResize)
160 ecore_x_window_move_resize(mX11Window, positionSize.x, positionSize.y, positionSize.width, positionSize.height);
161 mPosition = positionSize;
165 ecore_x_window_move(mX11Window, positionSize.x, positionSize.y);
166 mPosition = positionSize;
168 else if (needToResize)
170 ecore_x_window_resize(mX11Window, positionSize.width, positionSize.height);
171 mPosition = positionSize;
176 void WindowRenderSurface::Map()
178 ecore_x_window_show(mX11Window);
181 void WindowRenderSurface::StartRender()
185 bool WindowRenderSurface::PreRender( EglInterface&, Integration::GlAbstraction& )
187 // nothing to do for windows
191 void WindowRenderSurface::PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, DisplayConnection* displayConnection, unsigned int deltaTime, bool replacingSurface )
193 Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
194 eglImpl.SwapBuffers();
196 // When the window is deiconified, it approves the deiconify operation to window manager after rendering
197 if(mNeedToApproveDeiconify)
199 // SwapBuffer is desychronized. So make sure to sychronize when window is deiconified.
200 glAbstraction.Finish();
202 XDisplay* display = AnyCast<XDisplay *>(displayConnection->GetDisplay());
204 #ifndef DALI_PROFILE_UBUNTU
205 /* client sends immediately reply message using value 1 */
208 xev.xclient.window = mX11Window;
209 xev.xclient.type = ClientMessage;
210 xev.xclient.message_type = ECORE_X_ATOM_E_DEICONIFY_APPROVE;
211 xev.xclient.format = 32;
212 xev.xclient.data.l[0] = mX11Window;
213 xev.xclient.data.l[1] = 1;
214 xev.xclient.data.l[2] = 0;
215 xev.xclient.data.l[3] = 0;
216 xev.xclient.data.l[4] = 0;
218 XSendEvent(display, mX11Window, false, ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, &xev);
219 #endif // DALI_PROFILE_UBUNTU
221 XSync(display, false);
223 mNeedToApproveDeiconify = false;
227 void WindowRenderSurface::StopRender()
231 void WindowRenderSurface::SetViewMode( ViewMode viewMode )
233 Ecore_X_Atom viewModeAtom( ecore_x_atom_get( "_E_COMP_3D_APP_WIN" ) );
235 if( viewModeAtom != None )
237 unsigned int value( static_cast<unsigned int>( viewMode ) );
238 ecore_x_window_prop_card32_set( mX11Window, viewModeAtom, &value, 1 );
242 void WindowRenderSurface::CreateXRenderable()
244 // if width or height are zero, go full screen.
245 if ( (mPosition.width == 0) || (mPosition.height == 0) )
247 // Default window size == screen size
251 ecore_x_screen_size_get( ecore_x_default_screen_get(), &mPosition.width, &mPosition.height );
254 if(mColorDepth == COLOR_DEPTH_32)
256 // create 32 bit window
257 mX11Window = ecore_x_window_argb_new( 0, mPosition.x, mPosition.y, mPosition.width, mPosition.height );
261 // create 24 bit window
262 mX11Window = ecore_x_window_new( 0, mPosition.x, mPosition.y, mPosition.width, mPosition.height );
265 if ( mX11Window == 0 )
267 DALI_ASSERT_ALWAYS(0 && "Failed to create X window");
270 // set up window title which will be helpful for debug utitilty
271 ecore_x_icccm_title_set( mX11Window, mTitle.c_str() );
272 ecore_x_netwm_name_set( mX11Window, mTitle.c_str() );
273 ecore_x_icccm_name_class_set( mX11Window, mTitle.c_str(), mClassName.c_str() );
275 // set up etc properties to match with ecore-evas
277 if( ( id = getenv("DESKTOP_STARTUP_ID") ) )
279 ecore_x_netwm_startup_id_set( mX11Window, id );
282 ecore_x_icccm_hints_set( mX11Window,
284 ECORE_X_WINDOW_STATE_HINT_NORMAL, // initial_state
291 // we SHOULD guarantee the x11 window was created in x server.
295 void WindowRenderSurface::UseExistingRenderable( unsigned int surfaceId )
297 mX11Window = static_cast< Ecore_X_Window >( surfaceId );
300 void WindowRenderSurface::ReleaseLock()