Performance Improvements: Remove unnecessary SwapBuffer calls
[platform/core/uifw/dali-adaptor.git] / adaptors / base / separate-update-render / render-thread.cpp
1 /*
2  * Copyright (c) 2015 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 "render-thread.h"
20
21 // EXTERNAL INCLUDES
22 #include <dali/integration-api/debug.h>
23
24 // INTERNAL INCLUDES
25 #include <base/interfaces/adaptor-internal-services.h>
26 #include <base/separate-update-render/thread-synchronization.h>
27 #include <base/environment-options.h>
28
29 namespace Dali
30 {
31
32 namespace Internal
33 {
34
35 namespace Adaptor
36 {
37
38 namespace
39 {
40 #if defined(DEBUG_ENABLED)
41 Integration::Log::Filter* gRenderLogFilter = Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_RENDER_THREAD");
42 #endif
43 }
44
45 RenderThread::RenderThread( ThreadSynchronization& sync,
46                             AdaptorInternalServices& adaptorInterfaces,
47                             const EnvironmentOptions& environmentOptions )
48 : mThreadSynchronization( sync ),
49   mCore( adaptorInterfaces.GetCore() ),
50   mThread( NULL ),
51   mEnvironmentOptions( environmentOptions ),
52   mRenderHelper( adaptorInterfaces )
53 {
54 }
55
56 RenderThread::~RenderThread()
57 {
58 }
59
60 void RenderThread::Start()
61 {
62   DALI_LOG_INFO( gRenderLogFilter, Debug::Verbose, "RenderThread::Start()\n");
63
64   // create the render thread, initially we are rendering
65   mThread = new pthread_t();
66   int error = pthread_create( mThread, NULL, InternalThreadEntryFunc, this );
67   DALI_ASSERT_ALWAYS( !error && "Return code from pthread_create() in RenderThread" );
68
69   mRenderHelper.Start();
70 }
71
72 void RenderThread::Stop()
73 {
74   DALI_LOG_INFO( gRenderLogFilter, Debug::Verbose, "RenderThread::Stop()\n");
75
76   mRenderHelper.Stop();
77
78   // shutdown the render thread and destroy the opengl context
79   if( mThread )
80   {
81     // wait for the thread to finish
82     pthread_join(*mThread, NULL);
83
84     delete mThread;
85     mThread = NULL;
86   }
87 }
88
89 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
90 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
91 // The following methods are all executed inside render thread !!!
92 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
93 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
94
95 bool RenderThread::Run()
96 {
97   DALI_LOG_INFO( gRenderLogFilter, Debug::Verbose, "RenderThread::Run\n");
98
99   // Install a function for logging
100   mEnvironmentOptions.InstallLogFunction();
101
102   mRenderHelper.InitializeEgl();
103
104   // tell core it has a context
105   mCore.ContextCreated();
106
107   Dali::Integration::RenderStatus renderStatus;
108   RenderRequest* request = NULL;
109
110   // Render loop, we stay inside here when rendering
111   while( mThreadSynchronization.RenderReady( request ) )
112   {
113     DALI_LOG_INFO( gRenderLogFilter, Debug::Verbose, "RenderThread::Run. 1 - RenderReady\n");
114
115     // Consume any pending events to avoid memory leaks
116     DALI_LOG_INFO( gRenderLogFilter, Debug::Verbose, "RenderThread::Run. 2 - ConsumeEvents\n");
117     mRenderHelper.ConsumeEvents();
118
119     // Check if we've got a request from the main thread (e.g. replace surface)
120     if( request )
121     {
122       // Process the request, we should NOT render when we have a request
123       DALI_LOG_INFO( gRenderLogFilter, Debug::Verbose, "RenderThread::Run. 3 - Process requests\n");
124       ProcessRequest( request );
125     }
126     else
127     {
128       // No request to process so we render
129       if( mRenderHelper.PreRender() ) // Returns false if no surface onto which to render
130       {
131         // Render
132         DALI_LOG_INFO( gRenderLogFilter, Debug::Verbose, "RenderThread::Run. 3 - Core.Render()\n");
133
134         mThreadSynchronization.AddPerformanceMarker( PerformanceInterface::RENDER_START );
135         mCore.Render( renderStatus );
136         mThreadSynchronization.AddPerformanceMarker( PerformanceInterface::RENDER_END );
137
138         // Decrement the count of how far update is ahead of render
139         mThreadSynchronization.RenderFinished();
140
141         // Perform any post-render operations
142         if( renderStatus.NeedsPostRender() )
143         {
144           DALI_LOG_INFO( gRenderLogFilter, Debug::Verbose, "RenderThread::Run. 4 - PostRender()\n");
145           mRenderHelper.PostRender();
146         }
147       }
148     }
149
150     request = NULL; // Clear the request if it was set, no need to release memory
151   }
152
153   // Inform core of context destruction & shutdown EGL
154   mCore.ContextDestroyed();
155   mRenderHelper.ShutdownEgl();
156
157   // Uninstall the logging function
158   mEnvironmentOptions.UnInstallLogFunction();
159
160   return true;
161 }
162
163 void RenderThread::ProcessRequest( RenderRequest* request )
164 {
165   if( request != NULL )
166   {
167     switch(request->GetType())
168     {
169       case RenderRequest::REPLACE_SURFACE:
170       {
171         // change the surface
172         ReplaceSurfaceRequest* replaceSurfaceRequest = static_cast<ReplaceSurfaceRequest*>(request);
173         mRenderHelper.ReplaceSurface( replaceSurfaceRequest->GetSurface() );
174         replaceSurfaceRequest->ReplaceCompleted();
175         mThreadSynchronization.RenderInformSurfaceReplaced();
176         break;
177       }
178     }
179   }
180 }
181
182 } // namespace Adaptor
183
184 } // namespace Internal
185
186 } // namespace Dali