Merge "remove obsolete (unused) create default surface method and clean up documentat...
[platform/core/uifw/dali-adaptor.git] / adaptors / x11 / ecore-x-render-surface.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 "ecore-x-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 Debug::Filter* gRenderSurfaceLogFilter = Debug::Filter::New(Debug::Verbose, false, "LOG_ECORE_X_RENDER_SURFACE");
47 #endif
48
49 namespace ECore
50 {
51
52 namespace
53 {
54
55 static bool gXInitThreadsCalled = false;     ///< global to say whether XInitThreads has been called in this process
56
57 } // unnamed namespace
58
59 RenderSurface::RenderSurface( SurfaceType type,
60                               Dali::PositionSize positionSize,
61                               Any surface,
62                               Any display,
63                               const std::string& name,
64                               bool isTransparent)
65 : mMainDisplay(NULL),
66   mType(type),
67   mPosition(positionSize),
68   mTitle(name),
69   mColorDepth(isTransparent ? COLOR_DEPTH_32 : COLOR_DEPTH_24),
70   mRenderNotification( NULL ),
71   mOwnSurface(false),
72   mOwnDisplay(false)
73 {
74   // see if there is a display in Any display
75   SetDisplay( display );
76 }
77
78 void RenderSurface::Init( Any surface )
79 {
80   // see if there is a surface in Any surface
81   unsigned int surfaceId  = GetSurfaceId( surface );
82
83   // if the surface is empty, create a new one.
84   if ( surfaceId == 0 )
85   {
86     // make sure XInitThreads is called
87     if ( !gXInitThreadsCalled )
88     {
89       XInitThreads();
90       gXInitThreadsCalled = true;
91     }
92
93     // we own the surface about to created
94     mOwnSurface = true;
95     CreateXRenderable();
96   }
97   else
98   {
99     // XLib should already be initialized so no point in calling XInitThreads
100     UseExistingRenderable( surfaceId );
101   }
102
103 #ifdef DEBUG_ENABLED
104   // prints out 'INFO: DALI: new RenderSurface, created display xx, used existing surface xx
105   // we can not use LOG_INFO because the surface can be created before Dali Core is created.
106   printf(  "INFO: DALI: new RenderSurface, %s display %p, %s %s surface %X \n",
107              mOwnDisplay?"created":"used existing",mMainDisplay,
108              mOwnSurface?"created":"used existing",
109              Dali::RenderSurface::PIXMAP==mType?" pixmap" :"window",
110              GetDrawable() );
111 #endif
112 }
113
114 RenderSurface::~RenderSurface()
115 {
116   // release the display connection if we use our own
117   if( mOwnDisplay )
118   {
119     if( mMainDisplay )
120     {
121       // NOTE, on 64bit desktop with some NVidia driver versions this crashes
122 #ifdef _ARCH_ARM_
123       XCloseDisplay( mMainDisplay );
124 #endif
125     }
126   }
127 }
128
129 Ecore_X_Window RenderSurface::GetXWindow()
130 {
131   return 0;
132 }
133
134 XDisplay* RenderSurface::GetMainDisplay()
135 {
136   return mMainDisplay;
137 }
138
139 void RenderSurface::SetRenderNotification( TriggerEvent* renderNotification )
140 {
141   mRenderNotification = renderNotification;
142 }
143
144 Ecore_X_Drawable RenderSurface::GetDrawable()
145 {
146   return 0;
147 }
148
149 Any RenderSurface::GetDisplay()
150 {
151   // this getter is used by main thread so we need to return the main thread version of the display
152   return Any( ecore_x_display_get() );
153 }
154
155 PositionSize RenderSurface::GetPositionSize() const
156 {
157   return mPosition;
158 }
159
160 void RenderSurface::MoveResize( Dali::PositionSize positionSize )
161 {
162   // nothing to do in base class
163 }
164
165 void RenderSurface::GetDpi( unsigned int& dpiHorizontal, unsigned int& dpiVertical ) const
166 {
167   // calculate DPI
168   float xres, yres;
169
170   // 1 inch = 25.4 millimeters
171   xres = ecore_x_dpi_get();
172   yres = ecore_x_dpi_get();
173
174   dpiHorizontal = int(xres + 0.5f);  // rounding
175   dpiVertical   = int(yres + 0.5f);
176 }
177
178 void RenderSurface::Map()
179 {
180 }
181
182 void RenderSurface::TransferDisplayOwner( Internal::Adaptor::RenderSurface& newSurface )
183 {
184   // if we don't own the display return
185   if( mOwnDisplay == false )
186   {
187     return;
188   }
189
190   RenderSurface* other = dynamic_cast< RenderSurface* >( &newSurface );
191   if( other )
192   {
193     // if both surfaces share the same display, and this surface owns it,
194     // then transfer the ownership to the new surface
195     if( other->mMainDisplay == mMainDisplay )
196     {
197       mOwnDisplay = false;
198       other->mOwnDisplay = true;
199     }
200   }
201 }
202
203 void RenderSurface::ConsumeEvents()
204 {
205   // if the render surface has own display, check events so that we can flush the queue and avoid
206   // any potential memory leaks in X
207   if( mOwnDisplay )
208   {
209     // looping if events remain
210     int events( 0 );
211     do
212     {
213       // Check if there are any events in the queue
214       events = XEventsQueued( mMainDisplay, QueuedAfterFlush );
215
216       if ( events > 0 )
217       {
218         // Just flush event to prevent memory leak from event queue as the events get built up in
219         // memory but are only deleted when we retrieve them
220         XEvent ev;
221         XNextEvent( mMainDisplay, &ev );
222       }
223     }
224     while( events > 0 );
225   }
226 }
227
228 void RenderSurface::SetViewMode( ViewMode )
229 {
230 }
231
232 void RenderSurface::SetDisplay( Any display )
233 {
234   // the render surface can be passed either EFL e-core types, or x11 types
235   // we use boost any to determine at run time which type
236
237   if ( display.Empty() == false )
238   {
239     // check we have a valid type
240     DALI_ASSERT_ALWAYS( ( ( display.GetType() == typeid (Ecore_X_Display *)) ||
241                           ( display.GetType() == typeid (XDisplay *) ) )
242                         &&
243                         "Display type is invalid" );
244
245     mOwnDisplay = false;
246
247     // display may point to EcoreXDisplay so may need to cast
248     if( display.GetType() == typeid (Ecore_X_Display*) )
249     {
250       mMainDisplay = static_cast< XDisplay* >( AnyCast< Ecore_X_Display* >( display ) );
251     }
252     else
253     {
254       mMainDisplay = AnyCast< XDisplay* >( display );
255     }
256   }
257   else
258   {
259     mOwnDisplay = true;
260     // mMainDisplay = (XDisplay*)ecore_x_display_get();
261     // Because of DDK issue, we need to use separated x display instead of ecore default display
262     mMainDisplay = XOpenDisplay(0);
263   }
264 }
265
266 unsigned int RenderSurface::GetSurfaceId( Any surface ) const
267 {
268   unsigned int surfaceId = 0;
269
270   if ( surface.Empty() == false )
271   {
272     // check we have a valid type
273     DALI_ASSERT_ALWAYS( ( (surface.GetType() == typeid (XWindow) ) ||
274                           (surface.GetType() == typeid (Ecore_X_Window) ) )
275                         && "Surface type is invalid" );
276
277     if ( surface.GetType() == typeid (Ecore_X_Window) )
278     {
279       surfaceId = AnyCast<Ecore_X_Window>( surface );
280     }
281     else
282     {
283       surfaceId = AnyCast<XWindow>( surface );
284     }
285   }
286   return surfaceId;
287 }
288
289 } // namespace ECore
290
291 } // namespace Adaptor
292
293 } // namespace Internal
294
295 } // namespace Dali