Lifecycle controller
[platform/core/uifw/dali-adaptor.git] / adaptors / x11 / pixmap-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 "pixmap-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 PixmapRenderSurface::PixmapRenderSurface( Dali::PositionSize positionSize,
53                               Any surface,
54                               Any display,
55                               const std::string& name,
56                               bool isTransparent)
57 : RenderSurface( Dali::RenderSurface::PIXMAP, positionSize, surface, display, name, isTransparent ),
58   mSyncMode(SYNC_MODE_NONE),
59   mSyncReceived(false)
60 {
61   Init( surface );
62 }
63
64 PixmapRenderSurface::~PixmapRenderSurface()
65 {
66   // release the surface if we own one
67   if( mOwnSurface )
68   {
69     // if we did create the pixmap, delete the pixmap
70     DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::General, "Own pixmap (%x) freed\n", mX11Pixmap );
71     ecore_x_pixmap_free( mX11Pixmap );
72   }
73 }
74
75 Ecore_X_Drawable PixmapRenderSurface::GetDrawable()
76 {
77   return (Ecore_X_Drawable)mX11Pixmap;
78 }
79
80 Dali::RenderSurface::SurfaceType PixmapRenderSurface::GetType()
81 {
82   return Dali::RenderSurface::PIXMAP;
83 }
84
85 Any PixmapRenderSurface::GetSurface()
86 {
87   return Any( mX11Pixmap );
88 }
89
90 void PixmapRenderSurface::InitializeEgl( EglInterface& eglIf )
91 {
92   DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
93
94   EglImplementation& eglImpl = static_cast<EglImplementation&>( eglIf );
95   eglImpl.InitializeGles( reinterpret_cast< EGLNativeDisplayType >( mMainDisplay ) );
96
97   eglImpl.ChooseConfig(false, mColorDepth);
98 }
99
100 void PixmapRenderSurface::CreateEglSurface( EglInterface& eglIf )
101 {
102   DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
103
104   EglImplementation& eglImpl = static_cast<EglImplementation&>( eglIf );
105
106   // create the EGL surface
107   // need to cast to X handle as in 64bit system ECore handle is 32 bit whereas EGLnative and XWindow are 64 bit
108   XPixmap pixmap = static_cast< XPixmap>( mX11Pixmap );
109   eglImpl.CreateSurfacePixmap( (EGLNativePixmapType)pixmap, mColorDepth ); // reinterpret_cast does not compile
110 }
111
112 void PixmapRenderSurface::DestroyEglSurface( EglInterface& eglIf )
113 {
114   DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
115
116   EglImplementation& eglImpl = static_cast<EglImplementation&>( eglIf );
117   eglImpl.DestroySurface();
118 }
119
120 bool PixmapRenderSurface::ReplaceEGLSurface( EglInterface& eglIf )
121 {
122   DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
123
124   EglImplementation& eglImpl = static_cast<EglImplementation&>( eglIf );
125   eglImpl.InitializeGles( reinterpret_cast< EGLNativeDisplayType >( mMainDisplay ) );
126
127   // a new surface for the new pixmap
128   // need to cast to X handle as in 64bit system ECore handle is 32 bit whereas EGLnative and XWindow are 64 bit
129   XPixmap pixmap = static_cast< XPixmap>( mX11Pixmap );
130   return eglImpl.ReplaceSurfacePixmap( (EGLNativePixmapType)pixmap, // reinterpret_cast does not compile
131                                        reinterpret_cast< EGLNativeDisplayType >( mMainDisplay ) );
132 }
133
134 void PixmapRenderSurface::StartRender()
135 {
136   mSyncMode = SYNC_MODE_WAIT;
137 }
138
139 bool PixmapRenderSurface::PreRender( EglInterface&, Integration::GlAbstraction& )
140 {
141   // nothing to do for pixmaps
142   return true;
143 }
144
145 void PixmapRenderSurface::PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, unsigned int timeDelta, bool replacingSurface )
146 {
147   // flush gl instruction queue
148   glAbstraction.Flush();
149
150   // create damage for client applications which wish to know the update timing
151   if( mRenderNotification )
152   {
153     // use notification trigger
154     // Tell the event-thread to render the pixmap
155     mRenderNotification->Trigger();
156   }
157   else
158   {
159     // as a fallback, send damage event. This is needed until livebox is fixed to
160     // stop using damage events for render
161     Ecore_X_Drawable drawable = GetDrawable();
162
163     if( drawable )
164     {
165       XRectangle rect;
166       XserverRegion region;
167
168       rect.x = 0;
169       rect.y = 0;
170       rect.width = mPosition.width;
171       rect.height = mPosition.height;
172
173       // make a fixes region as updated area
174       region = XFixesCreateRegion( mMainDisplay, &rect, 1 );
175       // add damage event to updated drawable
176       XDamageAdd( mMainDisplay, (Drawable)drawable, region );
177       XFixesDestroyRegion( mMainDisplay, region );
178
179       XFlush( mMainDisplay );
180     }
181   }
182
183   AcquireLock( replacingSurface ? SYNC_MODE_NONE : SYNC_MODE_WAIT );
184 }
185
186 void PixmapRenderSurface::StopRender()
187 {
188   SetSyncMode(SYNC_MODE_NONE);
189   ReleaseLock();
190 }
191
192 void PixmapRenderSurface::CreateXRenderable()
193 {
194   // check we're creating one with a valid size
195   DALI_ASSERT_ALWAYS( mPosition.width > 0 && mPosition.height > 0 && "Pixmap size is invalid" );
196
197   // create the pixmap
198   mX11Pixmap = ecore_x_pixmap_new(0, mPosition.width, mPosition.height, mColorDepth);
199
200   // clear the pixmap
201   unsigned int foreground;
202   Ecore_X_GC gc;
203   foreground = 0;
204   gc = ecore_x_gc_new( mX11Pixmap,
205                        ECORE_X_GC_VALUE_MASK_FOREGROUND,
206                        &foreground );
207   ecore_x_drawable_rectangle_fill( mX11Pixmap, gc, 0, 0, mPosition.width, mPosition.height );
208
209   DALI_ASSERT_ALWAYS( mX11Pixmap && "Failed to create X pixmap" );
210
211   // we SHOULD guarantee the xpixmap/x11 window was created in x server.
212   ecore_x_sync();
213
214   ecore_x_gc_free(gc);
215 }
216
217 void PixmapRenderSurface::UseExistingRenderable( unsigned int surfaceId )
218 {
219   mX11Pixmap = static_cast< Ecore_X_Pixmap >( surfaceId );
220 }
221
222 void PixmapRenderSurface::SetSyncMode( SyncMode syncMode )
223 {
224   mSyncMode = syncMode;
225 }
226
227 void PixmapRenderSurface::AcquireLock( SyncMode syncMode )
228 {
229   boost::unique_lock< boost::mutex > lock( mSyncMutex );
230
231   // wait for sync
232   if( syncMode != SYNC_MODE_NONE &&
233       mSyncMode != SYNC_MODE_NONE &&
234       !mSyncReceived )
235   {
236     mSyncNotify.wait( lock );
237   }
238   mSyncReceived = false;
239 }
240
241 void PixmapRenderSurface::ReleaseLock()
242 {
243   {
244     boost::unique_lock< boost::mutex > lock( mSyncMutex );
245     mSyncReceived = true;
246   }
247
248   // wake render thread if it was waiting for the notify
249   mSyncNotify.notify_all();
250 }
251
252
253 } // namespace ECore
254
255 } // namespace Adaptor
256
257 } // namespace Internal
258
259 } // namespace Dali