summaryrefslogtreecommitdiffstats
blob: cd5e3f3cf3085afcfd9c252957394842ba64c6a8 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ANDROID_FRAMETRACKER_H
#define ANDROID_FRAMETRACKER_H

#include <stddef.h>

#include <utils/Mutex.h>
#include <utils/Timers.h>
#include <utils/RefBase.h>

namespace android {

class String8;
class Fence;

// FrameTracker tracks information about the most recently rendered frames. It
// uses a circular buffer of frame records, and is *NOT* thread-safe -
// mutexing must be done at a higher level if multi-threaded access is
// possible.
//
// Some of the time values tracked may be set either as a specific timestamp
// or a fence.  When a non-NULL fence is set for a given time value, the
// signal time of that fence is used instead of the timestamp.
class FrameTracker {

public:
    // NUM_FRAME_RECORDS is the size of the circular buffer used to track the
    // frame time history.
    enum { NUM_FRAME_RECORDS = 128 };

    enum { NUM_FRAME_BUCKETS = 7 };

    FrameTracker();

    // setDesiredPresentTime sets the time at which the current frame
    // should be presented to the user under ideal (i.e. zero latency)
    // conditions.
    void setDesiredPresentTime(nsecs_t desiredPresentTime);

    // setFrameReadyTime sets the time at which the current frame became ready
    // to be presented to the user.  For example, if the frame contents is
    // being written to memory by some asynchronous hardware, this would be
    // the time at which those writes completed.
    void setFrameReadyTime(nsecs_t readyTime);

    // setFrameReadyFence sets the fence that is used to get the time at which
    // the current frame became ready to be presented to the user.
    void setFrameReadyFence(const sp<Fence>& readyFence);

    // setActualPresentTime sets the timestamp at which the current frame became
    // visible to the user.
    void setActualPresentTime(nsecs_t displayTime);

    // setActualPresentFence sets the fence that is used to get the time
    // at which the current frame became visible to the user.
    void setActualPresentFence(const sp<Fence>& fence);

    // setDisplayRefreshPeriod sets the display refresh period in nanoseconds.
    // This is used to compute frame presentation duration statistics relative
    // to this period.
    void setDisplayRefreshPeriod(nsecs_t displayPeriod);

    // advanceFrame advances the frame tracker to the next frame.
    void advanceFrame();

    // clearStats clears the tracked frame stats.
    void clearStats();

    // getStats gets the tracked frame stats.
    void getStats(FrameStats* outStats) const;

    // logAndResetStats dumps the current statistics to the binary event log
    // and then resets the accumulated statistics to their initial values.
    void logAndResetStats(const String8& name);

    // dumpStats dump appends the current frame display time history to the result string.
    void dumpStats(String8& result) const;

private:
    struct FrameRecord {
        FrameRecord() :
            desiredPresentTime(0),
            frameReadyTime(0),
            actualPresentTime(0) {}
        nsecs_t desiredPresentTime;
        nsecs_t frameReadyTime;
        nsecs_t actualPresentTime;
        sp<Fence> frameReadyFence;
        sp<Fence> actualPresentFence;
    };

    // processFences iterates over all the frame records that have a fence set
    // and replaces that fence with a timestamp if the fence has signaled.  If
    // the fence is not signaled the record's displayTime is set to INT64_MAX.
    //
    // This method is const because although it modifies the frame records it
    // does so in such a way that the information represented should not
    // change.  This allows it to be called from the dump method.
    void processFencesLocked() const;

    // updateStatsLocked updates the running statistics that are gathered
    // about the frame times.
    void updateStatsLocked(size_t newFrameIdx) const;

    // resetFrameCounteresLocked sets all elements of the mNumFrames array to
    // 0.
    void resetFrameCountersLocked();

    // logStatsLocked dumps the current statistics to the binary event log.
    void logStatsLocked(const String8& name) const;

    // isFrameValidLocked returns true if the data for the given frame index is
    // valid and has all arrived (i.e. there are no oustanding fences).
    bool isFrameValidLocked(size_t idx) const;

    // mFrameRecords is the circular buffer storing the tracked data for each
    // frame.
    FrameRecord mFrameRecords[NUM_FRAME_RECORDS];

    // mOffset is the offset into mFrameRecords of the current frame.
    size_t mOffset;

    // mNumFences is the total number of fences set in the frame records.  It
    // is incremented each time a fence is added and decremented each time a
    // signaled fence is removed in processFences or if advanceFrame clobbers
    // a fence.
    //
    // The number of fences is tracked so that the run time of processFences
    // doesn't grow with NUM_FRAME_RECORDS.
    int mNumFences;

    // mNumFrames keeps a count of the number of frames with a duration in a
    // particular range of vsync periods.  Element n of the array stores the
    // number of frames with duration in the half-inclusive range
    // [2^n, 2^(n+1)).  The last element of the array contains the count for
    // all frames with duration greater than 2^(NUM_FRAME_BUCKETS-1).
    int32_t mNumFrames[NUM_FRAME_BUCKETS];

    // mDisplayPeriod is the display refresh period of the display for which
    // this FrameTracker is gathering information.
    nsecs_t mDisplayPeriod;

    // mMutex is used to protect access to all member variables.
    mutable Mutex mMutex;
};

}

#endif // ANDROID_FRAMETRACKER_H