Fraxinus  17.12-rc2
An IGT application
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  mSmartRender(false),
50  mLogging(false),
51  mBaseRenderInterval(40)
52 {
53  mLastFullRender = QDateTime::currentDateTime();
54  mCyclicLogger.reset(new CyclicActionLogger("Main Render timer"));
55 
56  mTimer = new QTimer(this);
57  connect(mTimer, SIGNAL(timeout()), this, SLOT(timeoutSlot()));
58 
59  this->sendRenderIntervalToTimer(mBaseRenderInterval);
60 }
61 
63 {
64  mTimer->start();
65 }
66 
68 {
69  mTimer->stop();
70  emit fps(0);
71 }
72 
74 {
75  return mTimer->isActive();
76 }
77 
79 {
80  mBaseRenderInterval = interval;
81  this->sendRenderIntervalToTimer(mBaseRenderInterval);
82 }
83 
85 {
86  mLogging = on;
87 }
88 
90 {
91  mSmartRender = val;
92 }
93 
94 void RenderLoop::sendRenderIntervalToTimer(int interval)
95 {
96  if (interval==mTimer->interval())
97  return;
98  if (interval == 0)
99  interval = 30;
100 
101  bool active = this->isRunning();
102  if (active)
103  mTimer->stop();
104  mTimer->setInterval(interval);
105  if (active)
106  mTimer->start();
107 }
108 
110 {
111  mLayoutWidgets.push_back(layout);
112 }
113 
114 
116 {
117  mLayoutWidgets.clear();
118 }
119 
120 void RenderLoop::timeoutSlot()
121 {
122  mCyclicLogger->begin();
123  mLastBeginRender = QDateTime::currentDateTime();
124  this->sendRenderIntervalToTimer(mBaseRenderInterval);
125 
126  emit preRender();
127 
128  this->renderViews();
129 
130  this->emitFPSIfRequired();
131 
132  int timeToNext = this->calculateTimeToNextRender();
133  this->sendRenderIntervalToTimer(timeToNext);
134 }
135 
136 void RenderLoop::renderViews()
137 {
138  bool smart = this->pollForSmartRenderingThisCycle();
139 
140  for (unsigned i=0; i<mLayoutWidgets.size(); ++i)
141  {
142  if (mLayoutWidgets[i])
143  {
144  if (!smart)
145  mLayoutWidgets[i]->setModified();
146  mLayoutWidgets[i]->render();
147  }
148  }
149 
150  mCyclicLogger->time("render");
151  emit renderFinished();
152 }
153 
154 bool RenderLoop::pollForSmartRenderingThisCycle()
155 {
156  // do a full render anyway at low rate. This is a convenience hack for rendering
157  // occational effects that the smart render is too dumb to see.
158  bool smart = mSmartRender;
159  int smartInterval = mTimer->interval() * 40;
160  int passed = mLastFullRender.time().msecsTo(QDateTime::currentDateTime().time());
161 
162  if (passed > smartInterval)
163  smart = false;
164  if (!smart)
165  mLastFullRender = QDateTime::currentDateTime();
166  return smart;
167 }
168 
169 void RenderLoop::emitFPSIfRequired()
170 {
171  if (mCyclicLogger->intervalPassed())
172  {
173  emit fps(mCyclicLogger->getFPS());
174  this->dumpStatistics();
175 // static int counter=0;
176 // if (++counter%3==0)
177 // reportDebug(mCyclicLogger->dumpStatisticsSmall());
178  mCyclicLogger->reset();
179  }
180 }
181 
182 void RenderLoop::dumpStatistics()
183 {
184  if (!mLogging)
185  return;
186 
187  static int counter=0;
188  if (++counter%3==0) // every third event
189  reportDebug(mCyclicLogger->dumpStatisticsSmall());
190 }
191 
192 int RenderLoop::calculateTimeToNextRender()
193 {
194  // tests show that the application wait between renderings even if the rendering uses more time
195  // than the interval. This hack shortens the wait time between renderings but keeps below the
196  // input update rate at all times.
197  int usage = mLastBeginRender.msecsTo(QDateTime::currentDateTime()); // time spent in rendering
198  int leftover = std::max(0, mTimer->interval() - usage); // time left of the rendering interval
199  int timeToNext = std::max(1, leftover); // always wait at least 1ms - give others time to do stuff
200  // std::cout << QString("setting interval %1, usage is %2").arg(timeToNext).arg(usage) << std::endl;
201  return timeToNext;
202 }
203 
204 } // namespace cx
205 
void renderFinished()
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 reportDebug(QString msg)
Definition: cxLogger.cpp:89
Namespace for all CustusX production code.