FrameInfo.h revision be3fba05e823f740f65b2679929347dc3dd282ad
1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#ifndef FRAMEINFO_H_
17#define FRAMEINFO_H_
18
19#include "utils/Macros.h"
20
21#include <cutils/compiler.h>
22#include <utils/Timers.h>
23
24#include <memory.h>
25#include <string>
26
27namespace android {
28namespace uirenderer {
29
30#define UI_THREAD_FRAME_INFO_SIZE 9
31
32enum class FrameInfoIndex {
33    Flags = 0,
34    IntendedVsync,
35    Vsync,
36    OldestInputEvent,
37    NewestInputEvent,
38    HandleInputStart,
39    AnimationStart,
40    PerformTraversalsStart,
41    DrawStart,
42    // End of UI frame info
43
44    SyncQueued,
45
46    SyncStart,
47    IssueDrawCommandsStart,
48    SwapBuffers,
49    FrameCompleted,
50
51    // Must be the last value!
52    NumIndexes
53};
54
55extern const std::string FrameInfoNames[];
56
57namespace FrameInfoFlags {
58    enum {
59        WindowLayoutChanged = 1 << 0,
60        RTAnimation = 1 << 1,
61        SurfaceCanvas = 1 << 2,
62        SkippedFrame = 1 << 3,
63    };
64};
65
66class ANDROID_API UiFrameInfoBuilder {
67public:
68    UiFrameInfoBuilder(int64_t* buffer) : mBuffer(buffer) {
69        memset(mBuffer, 0, UI_THREAD_FRAME_INFO_SIZE * sizeof(int64_t));
70    }
71
72    UiFrameInfoBuilder& setVsync(nsecs_t vsyncTime, nsecs_t intendedVsync) {
73        set(FrameInfoIndex::Vsync) = vsyncTime;
74        set(FrameInfoIndex::IntendedVsync) = intendedVsync;
75        // Pretend the other fields are all at vsync, too, so that naive
76        // duration calculations end up being 0 instead of very large
77        set(FrameInfoIndex::HandleInputStart) = vsyncTime;
78        set(FrameInfoIndex::AnimationStart) = vsyncTime;
79        set(FrameInfoIndex::PerformTraversalsStart) = vsyncTime;
80        set(FrameInfoIndex::DrawStart) = vsyncTime;
81        return *this;
82    }
83
84    UiFrameInfoBuilder& addFlag(int frameInfoFlag) {
85        set(FrameInfoIndex::Flags) |= static_cast<uint64_t>(frameInfoFlag);
86        return *this;
87    }
88
89private:
90    inline int64_t& set(FrameInfoIndex index) {
91        return mBuffer[static_cast<int>(index)];
92    }
93
94    int64_t* mBuffer;
95};
96
97class FrameInfo {
98public:
99    void importUiThreadInfo(int64_t* info);
100
101    void markSyncStart() {
102        set(FrameInfoIndex::SyncStart) = systemTime(CLOCK_MONOTONIC);
103    }
104
105    void markIssueDrawCommandsStart() {
106        set(FrameInfoIndex::IssueDrawCommandsStart) = systemTime(CLOCK_MONOTONIC);
107    }
108
109    void markSwapBuffers() {
110        set(FrameInfoIndex::SwapBuffers) = systemTime(CLOCK_MONOTONIC);
111    }
112
113    void markFrameCompleted() {
114        set(FrameInfoIndex::FrameCompleted) = systemTime(CLOCK_MONOTONIC);
115    }
116
117    void addFlag(int frameInfoFlag) {
118        set(FrameInfoIndex::Flags) |= static_cast<uint64_t>(frameInfoFlag);
119    }
120
121    inline int64_t operator[](FrameInfoIndex index) const {
122        return get(index);
123    }
124
125    inline int64_t operator[](int index) const {
126        if (index < 0 || index >= static_cast<int>(FrameInfoIndex::NumIndexes)) return 0;
127        return mFrameInfo[index];
128    }
129
130    inline int64_t duration(FrameInfoIndex start, FrameInfoIndex end) const {
131        int64_t endtime = get(end);
132        int64_t starttime = get(start);
133        int64_t gap = endtime - starttime;
134        gap = starttime > 0 ? gap : 0;
135        if (end > FrameInfoIndex::SyncQueued &&
136                start < FrameInfoIndex::SyncQueued) {
137            // Need to subtract out the time spent in a stalled state
138            // as this will be captured by the previous frame's info
139            int64_t offset = get(FrameInfoIndex::SyncStart)
140                    - get(FrameInfoIndex::SyncQueued);
141            if (offset > 0) {
142                gap -= offset;
143            }
144        }
145        return gap > 0 ? gap : 0;
146    }
147
148    inline int64_t totalDuration() const {
149        return duration(FrameInfoIndex::IntendedVsync, FrameInfoIndex::FrameCompleted);
150    }
151
152    inline int64_t& set(FrameInfoIndex index) {
153        return mFrameInfo[static_cast<int>(index)];
154    }
155
156    inline int64_t get(FrameInfoIndex index) const {
157        if (index == FrameInfoIndex::NumIndexes) return 0;
158        return mFrameInfo[static_cast<int>(index)];
159    }
160
161private:
162    int64_t mFrameInfo[static_cast<int>(FrameInfoIndex::NumIndexes)];
163};
164
165} /* namespace uirenderer */
166} /* namespace android */
167
168#endif /* FRAMEINFO_H_ */
169