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