blob: 45b57de0b5044b04037350e84310ae21e160bbec [file] [log] [blame]
John Reckba6adf62015-02-19 14:36:50 -08001/*
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>
John Reck4db3d172015-06-02 15:58:43 -070025#include <string>
John Reckba6adf62015-02-19 14:36:50 -080026
27namespace android {
28namespace uirenderer {
29
30#define UI_THREAD_FRAME_INFO_SIZE 9
31
John Reckc87be992015-02-20 10:57:22 -080032enum class FrameInfoIndex {
Chris Craik1b54fb22015-06-02 17:40:58 -070033 Flags = 0,
34 IntendedVsync,
35 Vsync,
36 OldestInputEvent,
37 NewestInputEvent,
38 HandleInputStart,
39 AnimationStart,
40 PerformTraversalsStart,
41 DrawStart,
John Reckba6adf62015-02-19 14:36:50 -080042 // End of UI frame info
43
John Reckbe3fba02015-07-06 13:49:58 -070044 SyncQueued,
45
Chris Craik1b54fb22015-06-02 17:40:58 -070046 SyncStart,
47 IssueDrawCommandsStart,
48 SwapBuffers,
49 FrameCompleted,
John Reckba6adf62015-02-19 14:36:50 -080050
John Reck2d5b8d72016-07-28 15:36:11 -070051 DequeueBufferDuration,
52 QueueBufferDuration,
53
John Reckba6adf62015-02-19 14:36:50 -080054 // Must be the last value!
John Reck65ddb152016-08-02 09:38:26 -070055 // Also must be kept in sync with FrameMetrics.java#FRAME_STATS_COUNT
Chris Craik1b54fb22015-06-02 17:40:58 -070056 NumIndexes
John Reckc87be992015-02-20 10:57:22 -080057};
John Reckba6adf62015-02-19 14:36:50 -080058
John Reck2a8bb052015-06-03 09:52:01 -070059extern const std::string FrameInfoNames[];
John Reck4db3d172015-06-02 15:58:43 -070060
Chris Craik1b54fb22015-06-02 17:40:58 -070061namespace FrameInfoFlags {
62 enum {
63 WindowLayoutChanged = 1 << 0,
64 RTAnimation = 1 << 1,
65 SurfaceCanvas = 1 << 2,
66 SkippedFrame = 1 << 3,
67 };
John Reckc87be992015-02-20 10:57:22 -080068};
John Reckba6adf62015-02-19 14:36:50 -080069
70class ANDROID_API UiFrameInfoBuilder {
71public:
72 UiFrameInfoBuilder(int64_t* buffer) : mBuffer(buffer) {
73 memset(mBuffer, 0, UI_THREAD_FRAME_INFO_SIZE * sizeof(int64_t));
74 }
75
76 UiFrameInfoBuilder& setVsync(nsecs_t vsyncTime, nsecs_t intendedVsync) {
Chris Craik1b54fb22015-06-02 17:40:58 -070077 set(FrameInfoIndex::Vsync) = vsyncTime;
78 set(FrameInfoIndex::IntendedVsync) = intendedVsync;
John Reckbf3c6022015-06-02 15:55:00 -070079 // Pretend the other fields are all at vsync, too, so that naive
80 // duration calculations end up being 0 instead of very large
Chris Craik1b54fb22015-06-02 17:40:58 -070081 set(FrameInfoIndex::HandleInputStart) = vsyncTime;
82 set(FrameInfoIndex::AnimationStart) = vsyncTime;
83 set(FrameInfoIndex::PerformTraversalsStart) = vsyncTime;
84 set(FrameInfoIndex::DrawStart) = vsyncTime;
John Reckba6adf62015-02-19 14:36:50 -080085 return *this;
86 }
87
Chris Craik1b54fb22015-06-02 17:40:58 -070088 UiFrameInfoBuilder& addFlag(int frameInfoFlag) {
89 set(FrameInfoIndex::Flags) |= static_cast<uint64_t>(frameInfoFlag);
John Reckba6adf62015-02-19 14:36:50 -080090 return *this;
91 }
92
93private:
John Reckc87be992015-02-20 10:57:22 -080094 inline int64_t& set(FrameInfoIndex index) {
95 return mBuffer[static_cast<int>(index)];
96 }
97
John Reckba6adf62015-02-19 14:36:50 -080098 int64_t* mBuffer;
99};
100
101class FrameInfo {
102public:
103 void importUiThreadInfo(int64_t* info);
104
105 void markSyncStart() {
Chris Craik1b54fb22015-06-02 17:40:58 -0700106 set(FrameInfoIndex::SyncStart) = systemTime(CLOCK_MONOTONIC);
John Reckba6adf62015-02-19 14:36:50 -0800107 }
108
109 void markIssueDrawCommandsStart() {
Chris Craik1b54fb22015-06-02 17:40:58 -0700110 set(FrameInfoIndex::IssueDrawCommandsStart) = systemTime(CLOCK_MONOTONIC);
John Reckba6adf62015-02-19 14:36:50 -0800111 }
112
113 void markSwapBuffers() {
Chris Craik1b54fb22015-06-02 17:40:58 -0700114 set(FrameInfoIndex::SwapBuffers) = systemTime(CLOCK_MONOTONIC);
John Reckba6adf62015-02-19 14:36:50 -0800115 }
116
117 void markFrameCompleted() {
Chris Craik1b54fb22015-06-02 17:40:58 -0700118 set(FrameInfoIndex::FrameCompleted) = systemTime(CLOCK_MONOTONIC);
John Reckba6adf62015-02-19 14:36:50 -0800119 }
120
Chris Craik1b54fb22015-06-02 17:40:58 -0700121 void addFlag(int frameInfoFlag) {
122 set(FrameInfoIndex::Flags) |= static_cast<uint64_t>(frameInfoFlag);
John Reck240ff622015-04-28 13:50:00 -0700123 }
124
Andres Morales06f5bc72015-12-15 15:21:31 -0800125 const int64_t* data() const {
126 return mFrameInfo;
127 }
128
John Reck41300272015-06-03 14:42:34 -0700129 inline int64_t operator[](FrameInfoIndex index) const {
John Reckbe3fba02015-07-06 13:49:58 -0700130 return get(index);
John Reckba6adf62015-02-19 14:36:50 -0800131 }
132
John Reck41300272015-06-03 14:42:34 -0700133 inline int64_t operator[](int index) const {
Chris Craik1b54fb22015-06-02 17:40:58 -0700134 if (index < 0 || index >= static_cast<int>(FrameInfoIndex::NumIndexes)) return 0;
John Reckc87be992015-02-20 10:57:22 -0800135 return mFrameInfo[index];
John Reckba6adf62015-02-19 14:36:50 -0800136 }
137
John Reck41300272015-06-03 14:42:34 -0700138 inline int64_t duration(FrameInfoIndex start, FrameInfoIndex end) const {
John Reckbe3fba02015-07-06 13:49:58 -0700139 int64_t endtime = get(end);
140 int64_t starttime = get(start);
John Reck41300272015-06-03 14:42:34 -0700141 int64_t gap = endtime - starttime;
142 gap = starttime > 0 ? gap : 0;
John Reckbe3fba02015-07-06 13:49:58 -0700143 if (end > FrameInfoIndex::SyncQueued &&
144 start < FrameInfoIndex::SyncQueued) {
145 // Need to subtract out the time spent in a stalled state
146 // as this will be captured by the previous frame's info
147 int64_t offset = get(FrameInfoIndex::SyncStart)
148 - get(FrameInfoIndex::SyncQueued);
149 if (offset > 0) {
150 gap -= offset;
151 }
152 }
John Reck41300272015-06-03 14:42:34 -0700153 return gap > 0 ? gap : 0;
154 }
155
156 inline int64_t totalDuration() const {
157 return duration(FrameInfoIndex::IntendedVsync, FrameInfoIndex::FrameCompleted);
158 }
159
John Reckc87be992015-02-20 10:57:22 -0800160 inline int64_t& set(FrameInfoIndex index) {
161 return mFrameInfo[static_cast<int>(index)];
162 }
163
John Reckbe3fba02015-07-06 13:49:58 -0700164 inline int64_t get(FrameInfoIndex index) const {
165 if (index == FrameInfoIndex::NumIndexes) return 0;
166 return mFrameInfo[static_cast<int>(index)];
167 }
168
169private:
Chris Craik1b54fb22015-06-02 17:40:58 -0700170 int64_t mFrameInfo[static_cast<int>(FrameInfoIndex::NumIndexes)];
John Reckba6adf62015-02-19 14:36:50 -0800171};
172
173} /* namespace uirenderer */
174} /* namespace android */
175
176#endif /* FRAMEINFO_H_ */