annotate layer/RenderTimer.h @ 1605:ae2d5f8ff005

When asked to render the whole view width, we need to wait for the layers to be ready before we can determine what the width is
author Chris Cannam
date Thu, 30 Apr 2020 14:47:13 +0100
parents a34a2a25907c
children
rev   line source
Chris@1074 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@1074 2
Chris@1074 3 /*
Chris@1074 4 Sonic Visualiser
Chris@1074 5 An audio file viewer and annotation editor.
Chris@1074 6 Centre for Digital Music, Queen Mary, University of London.
Chris@1074 7
Chris@1074 8 This program is free software; you can redistribute it and/or
Chris@1074 9 modify it under the terms of the GNU General Public License as
Chris@1074 10 published by the Free Software Foundation; either version 2 of the
Chris@1074 11 License, or (at your option) any later version. See the file
Chris@1074 12 COPYING included with this distribution for more information.
Chris@1074 13 */
Chris@1074 14
Chris@1074 15 #ifndef RENDER_TIMER_H
Chris@1074 16 #define RENDER_TIMER_H
Chris@1074 17
Chris@1074 18 #include <chrono>
Chris@1074 19
Chris@1074 20 class RenderTimer
Chris@1074 21 {
Chris@1074 22 public:
Chris@1074 23 enum Type {
Chris@1266 24 /// A normal rendering operation with normal responsiveness demands
Chris@1266 25 FastRender,
Chris@1074 26
Chris@1266 27 /// An operation that the user might accept being slower
Chris@1266 28 SlowRender,
Chris@1074 29
Chris@1266 30 /// An operation that should always complete, i.e. as if there
Chris@1266 31 /// were no RenderTimer in use, but without having to change
Chris@1266 32 /// client code structurally
Chris@1266 33 NoTimeout
Chris@1074 34 };
Chris@1074 35
Chris@1074 36 /**
Chris@1074 37 * Create a new RenderTimer and start timing. Make one of these
Chris@1074 38 * before rendering, and then call outOfTime() regularly during
Chris@1074 39 * rendering. If outOfTime() returns true, abandon rendering! and
Chris@1074 40 * schedule the rest for after some user responsiveness has
Chris@1074 41 * happened.
Chris@1074 42 */
Chris@1074 43 RenderTimer(Type t) :
Chris@1266 44 m_start(std::chrono::steady_clock::now()),
Chris@1266 45 m_haveLimits(true),
Chris@1266 46 m_minFraction(0.1),
Chris@1266 47 m_softLimit(0.1),
Chris@1266 48 m_hardLimit(0.2),
Chris@1266 49 m_softLimitOverridden(false) {
Chris@1074 50
Chris@1266 51 if (t == NoTimeout) {
Chris@1266 52 m_haveLimits = false;
Chris@1266 53 } else if (t == SlowRender) {
Chris@1266 54 m_softLimit = 0.2;
Chris@1266 55 m_hardLimit = 0.4;
Chris@1266 56 }
Chris@1074 57 }
Chris@1074 58
Chris@1074 59
Chris@1074 60 /**
Chris@1074 61 * Return true if we have run out of time and should suspend
Chris@1074 62 * rendering and handle user events instead. Call this regularly
Chris@1074 63 * during rendering work: fractionComplete should be an estimate
Chris@1074 64 * of how much of the work has been done as of this call, as a
Chris@1074 65 * number between 0.0 (none of it) and 1.0 (all of it).
Chris@1074 66 */
Chris@1074 67 bool outOfTime(double fractionComplete) {
Chris@1074 68
Chris@1266 69 if (!m_haveLimits || fractionComplete < m_minFraction) {
Chris@1266 70 return false;
Chris@1266 71 }
Chris@1266 72
Chris@1266 73 auto t = std::chrono::steady_clock::now();
Chris@1266 74 double elapsed = std::chrono::duration<double>(t - m_start).count();
Chris@1266 75
Chris@1266 76 if (elapsed > m_hardLimit) {
Chris@1266 77 return true;
Chris@1266 78 } else if (!m_softLimitOverridden && elapsed > m_softLimit) {
Chris@1266 79 if (fractionComplete > 0.6) {
Chris@1266 80 // If we're significantly more than half way by the
Chris@1266 81 // time we reach the soft limit, ignore it (though
Chris@1266 82 // always respect the hard limit, above). Otherwise
Chris@1266 83 // respect the soft limit and report out of time now.
Chris@1266 84 m_softLimitOverridden = true;
Chris@1266 85 } else {
Chris@1266 86 return true;
Chris@1266 87 }
Chris@1266 88 }
Chris@1074 89
Chris@1266 90 return false;
Chris@1074 91 }
Chris@1074 92
Chris@1221 93 double secondsPerItem(int itemsRendered) const {
Chris@1221 94
Chris@1221 95 if (itemsRendered == 0) return 0.0;
Chris@1221 96
Chris@1266 97 auto t = std::chrono::steady_clock::now();
Chris@1266 98 double elapsed = std::chrono::duration<double>(t - m_start).count();
Chris@1221 99
Chris@1221 100 return elapsed / itemsRendered;
Chris@1221 101 }
Chris@1221 102
Chris@1074 103 private:
Chris@1074 104 std::chrono::time_point<std::chrono::steady_clock> m_start;
Chris@1074 105 bool m_haveLimits;
Chris@1221 106 double m_minFraction; // proportion, 0.0 -> 1.0
Chris@1221 107 double m_softLimit; // seconds
Chris@1221 108 double m_hardLimit; // seconds
Chris@1074 109 bool m_softLimitOverridden;
Chris@1074 110 };
Chris@1074 111
Chris@1074 112 #endif