CustusX  16.5.0-rc9
An IGT application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
cxRenderLoop.cpp
Go to the documentation of this file.
1 /*=========================================================================
2 This file is part of CustusX, an Image Guided Therapy Application.
3 
4 Copyright (c) 2008-2014, SINTEF Department of Medical Technology
5 All rights reserved.
6 
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9 
10 1. Redistributions of source code must retain the above copyright notice,
11  this list of conditions and the following disclaimer.
12 
13 2. Redistributions in binary form must reproduce the above copyright notice,
14  this list of conditions and the following disclaimer in the documentation
15  and/or other materials provided with the distribution.
16 
17 3. Neither the name of the copyright holder nor the names of its contributors
18  may be used to endorse or promote products derived from this software
19  without specific prior written permission.
20 
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 =========================================================================*/
32 #include "cxRenderLoop.h"
33 
34 #include "cxCyclicActionLogger.h"
35 #include <QTimer>
36 #include "cxView.h"
37 #include "vtkRenderWindow.h"
38 #include "cxTypeConversions.h"
39 #include "cxLogger.h"
40 #include "cxViewCollectionWidget.h"
41 
42 
43 namespace cx
44 {
45 
47  QObject(NULL),
48  mTimer(NULL),
49  mPreRenderSignalRequested(false),
50  mSmartRender(false),
51  mLogging(false),
52  mBaseRenderInterval(40)
53 {
54  mLastFullRender = QDateTime::currentDateTime();
55  mCyclicLogger.reset(new CyclicActionLogger("Main Render timer"));
56 
57  mTimer = new QTimer(this);
58  connect(mTimer, SIGNAL(timeout()), this, SLOT(timeoutSlot()));
59 
60  this->sendRenderIntervalToTimer(mBaseRenderInterval);
61 }
62 
64 {
65  mTimer->start();
66 }
67 
69 {
70  mTimer->stop();
71  emit fps(0);
72 }
73 
75 {
76  return mTimer->isActive();
77 }
78 
80 {
81  mPreRenderSignalRequested = true;
82 }
83 
85 {
86  mBaseRenderInterval = interval;
87  this->sendRenderIntervalToTimer(mBaseRenderInterval);
88 }
89 
91 {
92  mLogging = on;
93 }
94 
96 {
97  mSmartRender = val;
98 }
99 
100 void RenderLoop::sendRenderIntervalToTimer(int interval)
101 {
102  if (interval==mTimer->interval())
103  return;
104  if (interval == 0)
105  interval = 30;
106 
107  bool active = this->isRunning();
108  if (active)
109  mTimer->stop();
110  mTimer->setInterval(interval);
111  if (active)
112  mTimer->start();
113 }
114 
116 {
117  mLayoutWidgets.push_back(layout);
118 }
119 
120 
122 {
123  mLayoutWidgets.clear();
124 }
125 
126 void RenderLoop::timeoutSlot()
127 {
128  mCyclicLogger->begin();
129  mLastBeginRender = QDateTime::currentDateTime();
130  this->sendRenderIntervalToTimer(mBaseRenderInterval);
131 
132  this->emitPreRenderIfRequested();
133 
134  this->renderViews();
135 
136  this->emitFPSIfRequired();
137 
138  int timeToNext = this->calculateTimeToNextRender();
139  this->sendRenderIntervalToTimer(timeToNext);
140 }
141 
142 void RenderLoop::emitPreRenderIfRequested()
143 {
144  if(mPreRenderSignalRequested)
145  {
146  emit preRender();
147  mPreRenderSignalRequested = false;
148  }
149  // mRenderTimer->time("prerender");
150 }
151 
152 void RenderLoop::renderViews()
153 {
154  bool smart = this->pollForSmartRenderingThisCycle();
155 
156  for (unsigned i=0; i<mLayoutWidgets.size(); ++i)
157  {
158  if (mLayoutWidgets[i])
159  {
160  if (!smart)
161  mLayoutWidgets[i]->setModified();
162  mLayoutWidgets[i]->render();
163  }
164  }
165 
166  mCyclicLogger->time("render");
167 }
168 
169 bool RenderLoop::pollForSmartRenderingThisCycle()
170 {
171  // do a full render anyway at low rate. This is a convenience hack for rendering
172  // occational effects that the smart render is too dumb to see.
173  bool smart = mSmartRender;
174  int smartInterval = mTimer->interval() * 40;
175  int passed = mLastFullRender.time().msecsTo(QDateTime::currentDateTime().time());
176 
177  if (passed > smartInterval)
178  smart = false;
179  if (!smart)
180  mLastFullRender = QDateTime::currentDateTime();
181  return smart;
182 }
183 
184 void RenderLoop::emitFPSIfRequired()
185 {
186  if (mCyclicLogger->intervalPassed())
187  {
188  emit fps(mCyclicLogger->getFPS());
189  this->dumpStatistics();
190 // static int counter=0;
191 // if (++counter%3==0)
192 // reportDebug(mCyclicLogger->dumpStatisticsSmall());
193  mCyclicLogger->reset();
194  }
195 }
196 
197 void RenderLoop::dumpStatistics()
198 {
199  if (!mLogging)
200  return;
201 
202  static int counter=0;
203  if (++counter%3==0) // every third event
204  reportDebug(mCyclicLogger->dumpStatisticsSmall());
205 }
206 
207 int RenderLoop::calculateTimeToNextRender()
208 {
209  // tests show that the application wait between renderings even if the rendering uses more time
210  // than the interval. This hack shortens the wait time between renderings but keeps below the
211  // input update rate at all times.
212  int usage = mLastBeginRender.msecsTo(QDateTime::currentDateTime()); // time spent in rendering
213  int leftover = std::max(0, mTimer->interval() - usage); // time left of the rendering interval
214  int timeToNext = std::max(1, leftover); // always wait at least 1ms - give others time to do stuff
215  // std::cout << QString("setting interval %1, usage is %2").arg(timeToNext).arg(usage) << std::endl;
216  return timeToNext;
217 }
218 
219 } // namespace cx
220 
void setRenderingInterval(int interval)
void fps(int number)
Emits number of frames per second.
bool isRunning() const
void addLayout(ViewCollectionWidget *layout)
void setLogging(bool on)
void setSmartRender(bool val)
If set: Render only views with modified props using the given interval, render nonmodified at a slowe...
void requestPreRenderSignal()
void reportDebug(QString msg)
Definition: cxLogger.cpp:89