Ensure XEvent queue for the render display is flushed
[platform/core/uifw/dali-adaptor.git] / adaptors / base / render-thread.h
1 #ifndef __DALI_INTERNAL_RENDER_THREAD_H__
2 #define __DALI_INTERNAL_RENDER_THREAD_H__
3
4 //
5 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
6 //
7 // Licensed under the Flora License, Version 1.0 (the License);
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 //
11 //     http://floralicense.org/license/
12 //
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an AS IS BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
18 //
19
20 // EXTERNAL INCLUDES
21 #include <boost/thread.hpp>
22
23 // INTERNAL INCLUDES
24 #include <base/interfaces/egl-interface.h>
25 #include <internal/common/render-surface-impl.h> // needed for Dali::Internal::Adaptor::RenderSurface
26
27
28 namespace Dali
29 {
30
31 namespace Integration
32 {
33 class GlAbstraction;
34 class Core;
35 }
36
37 namespace Internal
38 {
39 namespace Adaptor
40 {
41
42 class AdaptorInternalServices;
43 class RenderSurface;
44 class UpdateRenderSynchronization;
45 class EglFactoryInterface;
46 class LogOptions;
47
48 /**
49  * The render-thread is responsible for calling Core::Render() after each update.
50  */
51 class RenderThread
52 {
53 public:
54   /**
55    * Create the render-thread; this will not do anything until Start() is called.
56    * @param[in] sync update-render synchronization object
57    * @param[in] adaptorInterfaces base adaptor interface
58    * @param[in] logOptions log options
59
60    */
61   RenderThread( UpdateRenderSynchronization& sync,
62                 AdaptorInternalServices& adaptorInterfaces,
63                 const LogOptions& logOptions );
64
65   /**
66    * Virtual Destructor
67    */
68   virtual ~RenderThread();
69
70 public:
71
72   /**
73    * Starts the render-thread
74    */
75   void Start();
76
77   /**
78    * Stops the render-thread
79    */
80   void Stop();
81
82   /**
83    * Replaces the rendering surface. This method returns immediately
84    * You can call WaitForSurfaceReplaceComplete to block until the
85    * replace is completed in render thread. Note, you need to make sure
86    * that render thread is actually running!!!
87    */
88   void ReplaceSurface( RenderSurface* surface );
89
90   /**
91    * Blocks until surface replace has been completed
92    */
93   void WaitForSurfaceReplaceComplete();
94
95   /**
96    * Sets the EGL VSync mode synchronisation with the display.
97    * @param syncMode to use
98    */
99   void SetVSyncMode( EglInterface::SyncMode syncMode );
100
101   /**
102    * Offscreen was posted to onscreen
103    */
104   void RenderSync();
105
106 private: // Render thread side helpers
107
108   /**
109    * This method is used by the Render thread for rendering the Core to the screen.
110    * Called from render thread
111    * @return true, if the thread finishes properly.
112    */
113   bool Run();
114
115   /**
116    * Initializes EGL.
117    * Called from render thread
118    */
119   void InitializeEgl();
120
121   /**
122    * Check if display has events
123    * Called from render thread
124    */
125   void ConsumeEvents();
126
127   /**
128    * Check if main thread posted updates
129    * Called from render thread
130    */
131   void CheckForUpdates();
132
133   /**
134    * Changes the rendering surface
135    * Used for replacing pixmaps due to resizing
136    * Called from render thread
137    * @param newSurface to use
138    */
139   void ChangeSurface( RenderSurface* newSurface );
140
141   /**
142    * Notify the main thread that surface has really been changed
143    */
144   void NotifySurfaceChangeCompleted();
145
146   /**
147    * Shuts down EGL.
148    * Called from render thread
149    */
150   void ShutdownEgl();
151
152   /**
153    * Called before core renders the scene
154    * Called from render thread
155    * @return true if successful and Core::Render should be called.
156    */
157   bool PreRender();
158
159   /**
160    * Called after core has rendered the scene
161    * Called from render thread
162    * @param[in] timeDelta Time since PostRender was last called in microseconds
163    */
164   void PostRender( unsigned int timeDelta );
165
166 private: // Data
167
168   UpdateRenderSynchronization&        mUpdateRenderSync; ///< Used to synchronize the update & render threads
169   Dali::Integration::Core&            mCore;             ///< Dali core reference
170   Integration::GlAbstraction&         mGLES;             ///< GL abstraction rerefence
171   EglFactoryInterface*                mEglFactory;       ///< Factory class to create EGL implementation
172   EglInterface*                       mEGL;              ///< Interface to EGL implementation
173
174   boost::thread*                      mThread;           ///< render thread
175   bool                                mUsingPixmap;      ///< whether we're using a pixmap or a window
176   bool                                mSurfaceReplacing; ///< whether the surface is replacing. If true, need to notify surface changing after rendering
177
178   /**
179    * Structure to hold values that are set by main thread and read in render thread
180    * There is two copies of this data to avoid locking and prevent concurrent access
181    */
182   struct RenderData
183   {
184     /**
185      * Default constructor to reset values
186      */
187     RenderData()
188     : replaceSurface( false ),
189       syncMode( EglInterface::FULL_SYNC ),
190       surface( NULL )
191     {
192     }
193
194     volatile int                replaceSurface; ///< whether the surface needs replacing
195     EglInterface::SyncMode      syncMode;       ///< sync mode for EGL
196     RenderSurface*              surface;        ///< Current surface
197   };
198
199   RenderData                mCurrent;             ///< Current values, must not be used from main thread
200   RenderData                mNewValues;           ///< New values, sent from main thread to render thread
201   boost::mutex              mThreadDataLock;      ///< mutex to lock values while reading them into render thread
202   volatile int              mNewDataAvailable;    ///< atomic flag to notify the render thread that there's new data
203
204   /**
205    * Helper class for sending message to render thread
206    */
207   class SendMessageGuard
208   {
209   public: // API
210     /**
211      * Constructor, sets the lock
212      */
213     SendMessageGuard( RenderThread& parent )
214     : mLock( parent.mThreadDataLock ), mFlag( &parent.mNewDataAvailable )
215     { // Nothing to do, unique lock will lock automatically and unlock when destructed
216     }
217     /**
218      * Destructor, releases lock and sets flag
219      */
220     ~SendMessageGuard()
221     {
222       // set the flag to tell render thread there are new values, ignoring the return value here
223       (void)__sync_or_and_fetch( mFlag, 1 );
224     }
225
226   private: // Data
227     boost::unique_lock< boost::mutex > mLock;
228     volatile int* mFlag;
229   };
230
231   // sync for waiting offscreen flushed to onscreen
232   boost::mutex              mPixmapSyncMutex;      ///< mutex to lock during waiting sync
233   boost::condition_variable mPixmapSyncNotify;     ///< condition to notify main thread that pixmap was flushed to onscreen
234   bool                      mPixmapSyncReceived;   ///< true, when a pixmap sync has occurred, (cleared after reading)
235   bool                      mPixmapSyncRunning;    ///< true, while render thread is running and needs to wait for pixmap syncs
236   unsigned long             mCurrentMicroSec;
237
238   // sync for waiting for surface change
239   boost::mutex              mSurfaceChangedMutex;  ///< mutex to lock during surface replacing
240   boost::condition_variable mSurfaceChangedNotify; ///< condition to notify main thread that surface has been changed
241   bool                      mSurfaceReplaceCompleted;///< true, while render thread is running and needs to wait for pixmap syncs
242   const LogOptions&         mLogOptions;           ///< Log options
243
244 };
245
246 } // namespace Adaptor
247
248 } // namespace Internal
249
250 } // namespace Dali
251
252 #endif // __DALI_INTERNAL_RENDER_THREAD_H__
253