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