Boost removal from pixmap
[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 #include <dali/devel-api/common/mutex.h>
32
33 // INTERNAL INCLUDES
34
35 #include <ecore-x-types.h>
36 #include <trigger-event.h>
37 #include <gl/egl-implementation.h>
38 #include <base/display-connection.h>
39 #include <base/conditional-wait.h>
40
41
42 namespace Dali
43 {
44
45 #if defined(DEBUG_ENABLED)
46 extern Debug::Filter* gRenderSurfaceLogFilter;
47 #endif
48
49 namespace ECore
50 {
51
52
53 struct PixmapRenderSurface::Impl
54 {
55   Internal::Adaptor::ConditionalWait  mSyncNotify;   ///< condition to notify main thread that pixmap was flushed to onscreen
56   Dali::Mutex                         mSyncMutex;    ///< mutex to lock during waiting sync
57   Ecore_X_Pixmap                      mX11Pixmap;    ///< X-Pixmap
58   SyncMode                            mSyncMode;     ///< Stores whether the post render should block waiting for compositor
59   bool                                mSyncReceived; ///< true, when a pixmap sync has occurred, (cleared after reading)
60 };
61
62 PixmapRenderSurface::PixmapRenderSurface(Dali::PositionSize positionSize,
63                                          Any surface,
64                                          const std::string& name,
65                                          bool isTransparent)
66 : EcoreXRenderSurface( positionSize, surface, name, isTransparent ),
67   mImpl( new Impl )
68 {
69   mImpl->mSyncMode = SYNC_MODE_NONE;
70   mImpl->mSyncReceived = false;
71   Init( surface );
72 }
73
74 PixmapRenderSurface::~PixmapRenderSurface()
75 {
76   // release the surface if we own one
77   if( mOwnSurface )
78   {
79     // if we did create the pixmap, delete the pixmap
80     DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::General, "Own pixmap (%x) freed\n", mImpl->mX11Pixmap );
81     ecore_x_pixmap_free( mImpl->mX11Pixmap );
82   }
83
84   delete mImpl;
85 }
86
87 Ecore_X_Drawable PixmapRenderSurface::GetDrawable()
88 {
89   return (Ecore_X_Drawable) mImpl->mX11Pixmap;
90 }
91
92 Any PixmapRenderSurface::GetSurface()
93 {
94   return Any( mImpl->mX11Pixmap );
95 }
96
97 void PixmapRenderSurface::InitializeEgl( EglInterface& egl )
98 {
99   DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
100
101   Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
102
103   eglImpl.ChooseConfig(false, mColorDepth);
104 }
105
106 void PixmapRenderSurface::CreateEglSurface( EglInterface& egl )
107 {
108   DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
109
110   Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
111
112   // create the EGL surface
113   // need to cast to X handle as in 64bit system ECore handle is 32 bit whereas EGLnative and XWindow are 64 bit
114   XPixmap pixmap = static_cast<XPixmap>( mImpl->mX11Pixmap );
115   eglImpl.CreateSurfacePixmap( (EGLNativePixmapType)pixmap, mColorDepth ); // reinterpret_cast does not compile
116 }
117
118 void PixmapRenderSurface::DestroyEglSurface( EglInterface& egl )
119 {
120   DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
121
122   Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
123   eglImpl.DestroySurface();
124 }
125
126 bool PixmapRenderSurface::ReplaceEGLSurface( EglInterface& egl )
127 {
128   DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
129
130   // a new surface for the new pixmap
131   // need to cast to X handle as in 64bit system ECore handle is 32 bit whereas EGLnative and XWindow are 64 bit
132   XPixmap pixmap = static_cast<XPixmap>( mImpl->mX11Pixmap );
133   Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
134
135   return eglImpl.ReplaceSurfacePixmap( (EGLNativePixmapType)pixmap ); // reinterpret_cast does not compile
136
137 }
138
139 void PixmapRenderSurface::StartRender()
140 {
141   mImpl->mSyncMode = SYNC_MODE_WAIT;
142 }
143
144 bool PixmapRenderSurface::PreRender( EglInterface&, Integration::GlAbstraction& )
145 {
146   // nothing to do for pixmaps
147   return true;
148 }
149
150 void PixmapRenderSurface::PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, DisplayConnection* displayConnection, unsigned int deltaTime, bool replacingSurface )
151 {
152   // flush gl instruction queue
153   glAbstraction.Flush();
154
155   // create damage for client applications which wish to know the update timing
156   if( mRenderNotification )
157   {
158     // use notification trigger
159     // Tell the event-thread to render the pixmap
160     mRenderNotification->Trigger();
161   }
162   else
163   {
164     // as a fallback, send damage event.
165     Ecore_X_Drawable drawable = GetDrawable();
166
167     if( drawable )
168     {
169       XRectangle rect;
170       XserverRegion region;
171
172       rect.x = 0;
173       rect.y = 0;
174       rect.width = mPosition.width;
175       rect.height = mPosition.height;
176
177       XDisplay* display = AnyCast<XDisplay*>(displayConnection->GetDisplay());
178
179       // make a fixes region as updated area
180       region = XFixesCreateRegion( display, &rect, 1 );
181       // add damage event to updated drawable
182       XDamageAdd( display, (Drawable)drawable, region );
183       XFixesDestroyRegion( display, region );
184
185       XFlush( display );
186     }
187   }
188
189   AcquireLock( replacingSurface ? SYNC_MODE_NONE : SYNC_MODE_WAIT );
190 }
191
192 void PixmapRenderSurface::StopRender()
193 {
194   SetSyncMode(SYNC_MODE_NONE);
195   ReleaseLock();
196 }
197
198 void PixmapRenderSurface::CreateXRenderable()
199 {
200   // check we're creating one with a valid size
201   DALI_ASSERT_ALWAYS( mPosition.width > 0 && mPosition.height > 0 && "Pixmap size is invalid" );
202
203   // create the pixmap
204   mImpl->mX11Pixmap = ecore_x_pixmap_new(0, mPosition.width, mPosition.height, mColorDepth);
205
206   // clear the pixmap
207   unsigned int foreground;
208   Ecore_X_GC gc;
209   foreground = 0;
210   gc = ecore_x_gc_new( mImpl->mX11Pixmap,
211                        ECORE_X_GC_VALUE_MASK_FOREGROUND,
212                        &foreground );
213
214   DALI_ASSERT_ALWAYS( gc && "CreateXRenderable(): failed to get gc" );
215
216   ecore_x_drawable_rectangle_fill( mImpl->mX11Pixmap, gc, 0, 0, mPosition.width, mPosition.height );
217
218   DALI_ASSERT_ALWAYS( mImpl->mX11Pixmap && "Failed to create X pixmap" );
219
220   // we SHOULD guarantee the xpixmap/x11 window was created in x server.
221   ecore_x_sync();
222
223   ecore_x_gc_free(gc);
224 }
225
226 void PixmapRenderSurface::UseExistingRenderable( unsigned int surfaceId )
227 {
228   mImpl->mX11Pixmap = static_cast< Ecore_X_Pixmap >( surfaceId );
229 }
230
231 void PixmapRenderSurface::SetSyncMode( SyncMode syncMode )
232 {
233   mImpl->mSyncMode = syncMode;
234 }
235
236 void PixmapRenderSurface::AcquireLock( SyncMode syncMode )
237 {
238   Dali::Mutex::ScopedLock lock( mImpl->mSyncMutex );
239
240   // wait for sync
241   if( syncMode != SYNC_MODE_NONE &&
242       mImpl->mSyncMode != SYNC_MODE_NONE &&
243       !mImpl->mSyncReceived )
244   {
245     mImpl->mSyncNotify.Wait( );
246   }
247   mImpl->mSyncReceived = false;
248 }
249
250 void PixmapRenderSurface::ReleaseLock()
251 {
252   {
253     Dali::Mutex::ScopedLock lock( mImpl->mSyncMutex );
254     mImpl->mSyncReceived = true;
255   }
256
257   // wake render thread if it was waiting for the notify
258   mImpl->mSyncNotify.Notify();
259 }
260
261 } // namespace ECore
262
263 } // namespace Dali