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