Merge "Fix build errors with GCC4.8." into tizen
[platform/core/uifw/dali-adaptor.git] / adaptors / x11 / window-render-surface-x.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
18 // CLASS HEADER
19 #include "window-render-surface.h"
20
21 // EXTERNAL INCLUDES
22 #include <X11/Xatom.h>
23 #include <X11/Xlib.h>
24 #include <X11/Xutil.h>
25
26 #include <X11/extensions/Xfixes.h> // for damage notify
27 #include <X11/extensions/Xdamage.h> // for damage notify
28
29 #include <dali/integration-api/gl-abstraction.h>
30 #include <dali/integration-api/debug.h>
31
32 // INTERNAL INCLUDES
33 #include <ecore-x-types.h>
34 #include <trigger-event.h>
35
36 namespace Dali
37 {
38
39 namespace Internal
40 {
41
42 namespace Adaptor
43 {
44
45 #if defined(DEBUG_ENABLED)
46 extern Debug::Filter* gRenderSurfaceLogFilter;
47 #endif
48
49 namespace ECore
50 {
51
52 namespace
53 {
54
55 const int MINIMUM_DIMENSION_CHANGE( 1 ); ///< Minimum change for window to be considered to have moved
56
57 } // unnamed namespace
58
59 WindowRenderSurface::WindowRenderSurface( Dali::PositionSize positionSize,
60                                           Any surface,
61                                           Any display,
62                                           const std::string& name,
63                                           bool isTransparent)
64 : RenderSurface( Dali::RenderSurface::WINDOW, positionSize, surface, display, name, isTransparent ),
65   mNeedToApproveDeiconify(false)
66 {
67   DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "Creating Window\n" );
68   Init( surface );
69 }
70
71 WindowRenderSurface::~WindowRenderSurface()
72 {
73   if( mOwnSurface )
74   {
75     ecore_x_window_free( mX11Window );
76   }
77 }
78
79 Ecore_X_Drawable WindowRenderSurface::GetDrawable()
80 {
81   // already an e-core type
82   return (Ecore_X_Drawable)mX11Window;
83 }
84
85 Dali::RenderSurface::SurfaceType WindowRenderSurface::GetType()
86 {
87   return Dali::RenderSurface::WINDOW;
88 }
89
90 Any WindowRenderSurface::GetSurface()
91 {
92   // already an e-core type
93   return Any( mX11Window );
94 }
95
96 Ecore_X_Window WindowRenderSurface::GetXWindow()
97 {
98   return mX11Window;
99 }
100
101 void WindowRenderSurface::RequestToApproveDeiconify()
102 {
103   mNeedToApproveDeiconify = true;
104 }
105
106 void WindowRenderSurface::InitializeEgl( EglInterface& eglIf )
107 {
108   DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
109
110   EglImplementation& eglImpl = static_cast<EglImplementation&>( eglIf );
111   eglImpl.InitializeGles( reinterpret_cast< EGLNativeDisplayType >( mMainDisplay ) );
112
113   eglImpl.ChooseConfig(true, mColorDepth);
114 }
115
116 void WindowRenderSurface::CreateEglSurface( EglInterface& eglIf )
117 {
118   DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
119
120   EglImplementation& eglImpl = static_cast<EglImplementation&>( eglIf );
121
122   // create the EGL surface
123   // need to cast to X handle as in 64bit system ECore handle is 32 bit whereas EGLnative and XWindow are 64 bit
124   XWindow window = static_cast< XWindow>( mX11Window );
125   eglImpl.CreateSurfaceWindow( (EGLNativeWindowType)window, mColorDepth ); // reinterpret_cast does not compile
126 }
127
128 void WindowRenderSurface::DestroyEglSurface( EglInterface& eglIf )
129 {
130   DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
131
132   EglImplementation& eglImpl = static_cast<EglImplementation&>( eglIf );
133   eglImpl.DestroySurface();
134 }
135
136 bool WindowRenderSurface::ReplaceEGLSurface( EglInterface& eglIf )
137 {
138   DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
139
140   EglImplementation& egl = static_cast<EglImplementation&>( eglIf );
141   egl.InitializeGles( reinterpret_cast< EGLNativeDisplayType >( mMainDisplay ) );
142
143   // need to cast to X handle as in 64bit system ECore handle is 32 bit whereas EGLnative and XWindow are 64 bit
144   XWindow window = static_cast< XWindow >( mX11Window );
145   return egl.ReplaceSurfaceWindow( (EGLNativeWindowType)window, // reinterpret_cast does not compile
146                                    reinterpret_cast< EGLNativeDisplayType >( mMainDisplay ) );
147 }
148
149 void WindowRenderSurface::MoveResize( Dali::PositionSize positionSize )
150 {
151   bool needToMove = false;
152   bool needToResize = false;
153
154   // check moving
155   if( (fabs(positionSize.x - mPosition.x) > MINIMUM_DIMENSION_CHANGE) ||
156       (fabs(positionSize.y - mPosition.y) > MINIMUM_DIMENSION_CHANGE) )
157   {
158     needToMove = true;
159   }
160
161   // check resizing
162   if( (fabs(positionSize.width - mPosition.width) > MINIMUM_DIMENSION_CHANGE) ||
163       (fabs(positionSize.height - mPosition.height) > MINIMUM_DIMENSION_CHANGE) )
164   {
165     needToResize = true;
166   }
167
168   if( needToMove &&  needToResize)
169   {
170     ecore_x_window_move_resize(mX11Window, positionSize.x, positionSize.y, positionSize.width, positionSize.height);
171     mPosition = positionSize;
172   }
173   else if(needToMove)
174   {
175     ecore_x_window_move(mX11Window, positionSize.x, positionSize.y);
176     mPosition = positionSize;
177   }
178   else if (needToResize)
179   {
180     ecore_x_window_resize(mX11Window, positionSize.width, positionSize.height);
181     mPosition = positionSize;
182   }
183
184 }
185
186 void WindowRenderSurface::Map()
187 {
188   ecore_x_window_show(mX11Window);
189 }
190
191 bool WindowRenderSurface::PreRender( EglInterface&, Integration::GlAbstraction& )
192 {
193   // nothing to do for windows
194   return true;
195 }
196
197 void WindowRenderSurface::PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, unsigned int, SyncMode )
198 {
199   EglImplementation& eglImpl = static_cast<EglImplementation&>( egl );
200   eglImpl.SwapBuffers();
201
202   // When the window is deiconified, it approves the deiconify operation to window manager after rendering
203   if(mNeedToApproveDeiconify)
204   {
205     // SwapBuffer is desychronized. So make sure to sychronize when window is deiconified.
206     glAbstraction.Finish();
207
208     /* client sends immediately reply message using value 1 */
209     ecore_x_client_message32_send(mX11Window,
210                         ECORE_X_ATOM_E_DEICONIFY_APPROVE,
211                         ECORE_X_EVENT_MASK_WINDOW_CONFIGURE,
212                         mX11Window, 1,
213                         0, 0, 0);
214
215     ecore_x_sync();
216
217     mNeedToApproveDeiconify = false;
218   }
219 }
220
221 void WindowRenderSurface::SetViewMode( ViewMode viewMode )
222 {
223   Ecore_X_Atom viewModeAtom( ecore_x_atom_get( "_E_COMP_3D_APP_WIN" ) );
224
225   if( viewModeAtom != None )
226   {
227     unsigned int value( static_cast<unsigned int>( viewMode ) );
228     ecore_x_window_prop_card32_set( mX11Window, viewModeAtom, &value, 1 );
229   }
230 }
231
232 void WindowRenderSurface::CreateXRenderable()
233 {
234    // if width or height are zero, go full screen.
235   if ( (mPosition.width == 0) || (mPosition.height == 0) )
236   {
237     // Default window size == screen size
238     mPosition.x = 0;
239     mPosition.y = 0;
240
241     ecore_x_screen_size_get( ecore_x_default_screen_get(), &mPosition.width, &mPosition.height );
242   }
243
244   if(mColorDepth == COLOR_DEPTH_32)
245   {
246     // create 32 bit window
247     mX11Window = ecore_x_window_argb_new( 0, mPosition.x, mPosition.y, mPosition.width, mPosition.height );
248   }
249   else
250   {
251     // create 24 bit window
252     mX11Window = ecore_x_window_new( 0, mPosition.x, mPosition.y, mPosition.width, mPosition.height );
253   }
254
255   if ( mX11Window == 0 )
256   {
257       DALI_ASSERT_ALWAYS(0 && "Failed to create X window");
258   }
259
260   // set up window title which will be helpful for debug utitilty
261   ecore_x_icccm_title_set( mX11Window, mTitle.c_str() );
262   ecore_x_netwm_name_set( mX11Window, mTitle.c_str() );
263
264   // set up etc properties to match with ecore-evas
265   char *id = NULL;
266   if( ( id = getenv("DESKTOP_STARTUP_ID") ) )
267   {
268     ecore_x_netwm_startup_id_set( mX11Window, id );
269   }
270
271   ecore_x_icccm_hints_set( mX11Window,
272                            1,                                // accepts_focus
273                            ECORE_X_WINDOW_STATE_HINT_NORMAL, // initial_state
274                            0,                                // icon_pixmap
275                            0,                                // icon_mask
276                            0,                                // icon_window
277                            0,                                // window_group
278                            0 );                              // is_urgent
279
280   // we SHOULD guarantee the x11 window was created in x server.
281   ecore_x_sync();
282 }
283
284 void WindowRenderSurface::UseExistingRenderable( unsigned int surfaceId )
285 {
286   mX11Window = static_cast< Ecore_X_Window >( surfaceId );
287 }
288
289 } // namespace ECore
290
291 } // namespace Adaptor
292
293 } // namespace Internal
294
295 } // namespace Dali