xref: /aosp_15_r20/external/skia/tools/timer/TimeUtils.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 // Copyright 2019 Google LLC
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef TimeUtils_DEFINED
6 #define TimeUtils_DEFINED
7 
8 #include "include/core/SkTypes.h"
9 #include "include/private/base/SkFloatingPoint.h"
10 
11 #include <climits>
12 #include <cmath>
13 
14 namespace TimeUtils {
15 // 32 bit value to hold a millisecond duration
16 using MSec = uint32_t;
17 
18 // Maximum representable milliseconds; 24d 20h 31m 23.647s
19 static constexpr MSec MSecMax = INT32_MAX;
20 
21 // Returns 0 if the timer is stopped. Behavior is undefined if the timer
22 // has been running longer than MSecMax.
NanosToMSec(double nanos)23 static inline MSec NanosToMSec(double nanos) {
24     const double msec = nanos * 1e-6;
25     SkASSERT(MSecMax >= msec);
26     return static_cast<MSec>(msec);
27 }
28 
NanosToSeconds(double nanos)29 static inline double NanosToSeconds(double nanos) {
30     return nanos * 1e-9;
31 }
32 
33 // Return the time scaled by "speed" and (if not zero) mod by period.
34 static inline float Scaled(float time, float speed, float period = 0) {
35     double value = time * speed;
36     if (period) {
37         value = ::fmod(value, (double)(period));
38     }
39     return (float)value;
40 }
41 
42 // Transitions from ends->mid->ends linearly over period time. The phase
43 // specifies a phase shift in time units.
PingPong(double time,float period,float phase,float ends,float mid)44 static inline float PingPong(double time,
45                              float period,
46                              float phase,
47                              float ends,
48                              float mid) {
49     double value = ::fmod(time + phase, period);
50     double half  = period / 2.0;
51     double diff  = ::fabs(value - half);
52     return (float)(ends + (1.0 - diff / half) * (mid - ends));
53 }
54 
SineWave(double time,float periodInSecs,float phaseInSecs,float min,float max)55 static inline float SineWave(double time,
56                              float periodInSecs,
57                              float phaseInSecs,
58                              float min,
59                              float max) {
60     if (periodInSecs < 0.f) {
61         return (min + max) / 2.f;
62     }
63     double t = NanosToSeconds(time) + phaseInSecs;
64     t *= 2 * SK_FloatPI / periodInSecs;
65     float halfAmplitude = (max - min) / 2.f;
66     return halfAmplitude * std::sin(t) + halfAmplitude + min;
67 }
68 }  // namespace TimeUtils
69 #endif
70