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