cbc587ecd4992c15f42cb23c64541d568d630e08
[platform/core/uifw/dali-adaptor.git] / adaptors / tizen / internal / common / ecore-x / ecore-x-render-surface.cpp
1 //
2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
3 //
4 // Licensed under the Flora License, Version 1.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://floralicense.org/license/
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 // CLASS HEADER
18 #include "ecore-x-render-surface.h"
19
20 // EXTERNAL INCLUDES
21 #include <X11/Xatom.h>
22 #include <X11/Xlib.h>
23 #include <X11/Xutil.h>
24
25 #include <X11/extensions/Xfixes.h> // for damage notify
26 #include <X11/extensions/Xdamage.h> // for damage notify
27
28 #include <dali/integration-api/gl-abstraction.h>
29 #include <dali/integration-api/debug.h>
30
31 // INTERNAL INCLUDES
32 #include <internal/common/ecore-x/ecore-x-types.h>
33 #include <internal/common/trigger-event.h>
34
35 namespace Dali
36 {
37
38 namespace Internal
39 {
40
41 namespace Adaptor
42 {
43
44 #if defined(DEBUG_ENABLED)
45 Debug::Filter* gRenderSurfaceLogFilter = Debug::Filter::New(Debug::Verbose, false, "LOG_ECORE_X_RENDER_SURFACE");
46 #endif
47
48 namespace ECoreX
49 {
50
51 namespace
52 {
53
54 const float MINIMUM_DIMENSION_CHANGE = 1.0f; ///< Minimum change for window to be considered to have moved
55 static bool gXInitThreadsCalled = false;     ///< global to say whether XInitThreads has been called in this process
56 const unsigned int MICROSECONDS_PER_SECOND = 1000000;
57 const unsigned int MILLISECONDS_PER_SECOND = 1000;
58
59 } // unnamed namespace
60
61 RenderSurface::RenderSurface( SurfaceType type,
62                               Dali::PositionSize positionSize,
63                               Any surface,
64                               Any display,
65                               const std::string& name,
66                               bool isTransparent)
67 : mMainDisplay(NULL),
68   mType(type),
69   mPosition(positionSize),
70   mTitle(name),
71   mColorDepth(isTransparent ? COLOR_DEPTH_32 : COLOR_DEPTH_24),
72   mRenderMode((type == PIXMAP) ? RENDER_SYNC : RENDER_DEFAULT),
73   mRenderNotification( NULL ),
74   mSyncReceived( false ),
75   mOwnSurface(false),
76   mOwnDisplay(false),
77   mIsStopped( false )
78 {
79   // see if there is a display in Any display
80   SetDisplay( display );
81 }
82
83 void RenderSurface::Init( Any surface )
84 {
85   // see if there is a surface in Any surface
86   unsigned int surfaceId  = GetSurfaceId( surface );
87
88   // if the surface is empty, create a new one.
89   if ( surfaceId == 0 )
90   {
91     // make sure XInitThreads is called
92     if ( !gXInitThreadsCalled )
93     {
94       XInitThreads();
95       gXInitThreadsCalled = true;
96     }
97
98     // we own the surface about to created
99     mOwnSurface = true;
100     CreateXRenderable();
101   }
102   else
103   {
104     // XLib should already be initialized so no point in calling XInitThreads
105     UseExistingRenderable( surfaceId );
106   }
107
108 #ifdef DEBUG_ENABLED
109   // prints out 'INFO: DALI: new RenderSurface, created display xx, used existing surface xx
110   // we can not use LOG_INFO because the surface can be created before Dali Core is created.
111   printf(  "INFO: DALI: new RenderSurface, %s display %p, %s %s surface %X \n",
112              mOwnDisplay?"created":"used existing",mMainDisplay,
113              mOwnSurface?"created":"used existing",
114              Dali::RenderSurface::PIXMAP==mType?" pixmap" :"window",
115              GetDrawable() );
116 #endif
117 }
118
119 RenderSurface::~RenderSurface()
120 {
121   // release the display connection if we use our own
122   if( mOwnDisplay )
123   {
124     if( mMainDisplay )
125     {
126       // NOTE, on 64bit desktop with some NVidia driver versions this crashes
127 #ifdef _ARCH_ARM_
128       XCloseDisplay( mMainDisplay );
129 #endif
130     }
131   }
132 }
133
134 Ecore_X_Window RenderSurface::GetXWindow()
135 {
136   return 0;
137 }
138
139 XDisplay* RenderSurface::GetMainDisplay()
140 {
141   return mMainDisplay;
142 }
143
144 void RenderSurface::SetRenderNotification( TriggerEvent* renderNotification )
145 {
146   mRenderNotification = renderNotification;
147 }
148
149 Ecore_X_Drawable RenderSurface::GetDrawable()
150 {
151   return 0;
152 }
153
154 Any RenderSurface::GetDisplay()
155 {
156   // this getter is used by main thread so we need to return the main thread version of the display
157   return Any( ecore_x_display_get() );
158 }
159
160 PositionSize RenderSurface::GetPositionSize() const
161 {
162   return mPosition;
163 }
164
165 void RenderSurface::SetRenderMode(RenderMode mode)
166 {
167   mRenderMode = mode;
168 }
169
170 Dali::RenderSurface::RenderMode RenderSurface::GetRenderMode() const
171 {
172   return mRenderMode;
173 }
174
175 void RenderSurface::MoveResize( Dali::PositionSize positionSize )
176 {
177   // nothing to do in base class
178 }
179
180 void RenderSurface::GetDpi( unsigned int& dpiHorizontal, unsigned int& dpiVertical ) const
181 {
182   // calculate DPI
183   float xres, yres;
184
185   // 1 inch = 25.4 millimeters
186   xres = ecore_x_dpi_get();
187   yres = ecore_x_dpi_get();
188
189   dpiHorizontal = int(xres + 0.5f);  // rounding
190   dpiVertical   = int(yres + 0.5f);
191 }
192
193 void RenderSurface::Map()
194 {
195 }
196
197 void RenderSurface::TransferDisplayOwner( Internal::Adaptor::RenderSurface& newSurface )
198 {
199   // if we don't own the display return
200   if( mOwnDisplay == false )
201   {
202     return;
203   }
204
205   RenderSurface* other = dynamic_cast< RenderSurface* >( &newSurface );
206   if( other )
207   {
208     // if both surfaces share the same display, and this surface owns it,
209     // then transfer the ownership to the new surface
210     if( other->mMainDisplay == mMainDisplay )
211     {
212       mOwnDisplay = false;
213       other->mOwnDisplay = true;
214     }
215   }
216 }
217
218 void RenderSurface::ConsumeEvents()
219 {
220   // if the render surface has own display, check events so that we can flush the queue and avoid
221   // any potential memory leaks in X
222   if( mOwnDisplay )
223   {
224     // looping if events remain
225     int events( 0 );
226     do
227     {
228       // Check if there are any events in the queue
229       events = XEventsQueued( mMainDisplay, QueuedAfterFlush );
230
231       if ( events > 0 )
232       {
233         // Just flush event to prevent memory leak from event queue as the events get built up in
234         // memory but are only deleted when we retrieve them
235         XEvent ev;
236         XNextEvent( mMainDisplay, &ev );
237       }
238     }
239     while( events > 0 );
240   }
241 }
242
243 void RenderSurface::StopRender()
244 {
245   // Stop blocking waiting for sync
246   SetSyncMode( RenderSurface::SYNC_MODE_NONE );
247   // Simulate a RenderSync in case render-thread is currently blocked
248   RenderSync();
249
250   mIsStopped = true;
251 }
252
253 void RenderSurface::SetDisplay( Any display )
254 {
255   // the render surface can be passed either EFL e-core types, or x11 types
256   // we use boost any to determine at run time which type
257
258   if ( display.Empty() == false )
259   {
260     // check we have a valid type
261     DALI_ASSERT_ALWAYS( ( ( display.GetType() == typeid (Ecore_X_Display *)) ||
262                           ( display.GetType() == typeid (XDisplay *) ) )
263                         &&
264                         "Display type is invalid" );
265
266     mOwnDisplay = false;
267
268     // display may point to EcoreXDisplay so may need to cast
269     if( display.GetType() == typeid (Ecore_X_Display*) )
270     {
271       mMainDisplay = static_cast< XDisplay* >( AnyCast< Ecore_X_Display* >( display ) );
272     }
273     else
274     {
275       mMainDisplay = AnyCast< XDisplay* >( display );
276     }
277   }
278   else
279   {
280     mOwnDisplay = true;
281     // mMainDisplay = (XDisplay*)ecore_x_display_get();
282     // Because of DDK issue, we need to use separated x display instead of ecore default display
283     mMainDisplay = XOpenDisplay(0);
284   }
285 }
286
287 unsigned int RenderSurface::GetSurfaceId( Any surface ) const
288 {
289   unsigned int surfaceId = 0;
290
291   if ( surface.Empty() == false )
292   {
293     // check we have a valid type
294     DALI_ASSERT_ALWAYS( ( (surface.GetType() == typeid (XWindow) ) ||
295                           (surface.GetType() == typeid (Ecore_X_Window) ) )
296                         && "Surface type is invalid" );
297
298     if ( surface.GetType() == typeid (Ecore_X_Window) )
299     {
300       surfaceId = AnyCast<Ecore_X_Window>( surface );
301     }
302     else
303     {
304       surfaceId = AnyCast<XWindow>( surface );
305     }
306   }
307   return surfaceId;
308 }
309
310 void RenderSurface::RenderSync()
311 {
312   // nothing to do
313 }
314
315 void RenderSurface::DoRenderSync( unsigned int timeDelta, SyncMode syncMode )
316 {
317   // Should block waiting for RenderSync?
318   if( mRenderMode == Dali::RenderSurface::RENDER_SYNC )
319   {
320     boost::unique_lock< boost::mutex > lock( mSyncMutex );
321
322     // wait for sync
323     if( syncMode != SYNC_MODE_NONE &&
324         mSyncMode != SYNC_MODE_NONE &&
325         !mSyncReceived )
326     {
327       mSyncNotify.wait( lock );
328     }
329     mSyncReceived = false;
330   }
331   // Software sync based on a timed delay?
332   else if( mRenderMode > Dali::RenderSurface::RENDER_SYNC )
333   {
334     unsigned int syncPeriod( MICROSECONDS_PER_SECOND / static_cast< unsigned int >( mRenderMode ) - MILLISECONDS_PER_SECOND );
335     if( timeDelta < syncPeriod )
336     {
337       usleep( syncPeriod - timeDelta );
338     }
339   }
340 }
341
342 } // namespace ECoreX
343
344 } // namespace Adaptor
345
346 } // namespace Internal
347
348 } // namespace Dali