blob: f5bfedde2f923e48ee867fb36c3a760cb2f0bbfa [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
Steven Thomas6fabb5a2020-08-21 16:56:08 -070030#define UI_THREAD_FRAME_INFO_SIZE 10
John Reckba6adf62015-02-19 14:36:50 -080031
John Reckc87be992015-02-20 10:57:22 -080032enum class FrameInfoIndex {
Chris Craik1b54fb22015-06-02 17:40:58 -070033 Flags = 0,
Steven Thomas6fabb5a2020-08-21 16:56:08 -070034 FrameTimelineVsyncId,
Chris Craik1b54fb22015-06-02 17:40:58 -070035 IntendedVsync,
36 Vsync,
37 OldestInputEvent,
38 NewestInputEvent,
39 HandleInputStart,
40 AnimationStart,
41 PerformTraversalsStart,
42 DrawStart,
John Reckba6adf62015-02-19 14:36:50 -080043 // End of UI frame info
44
John Reckbe3fba02015-07-06 13:49:58 -070045 SyncQueued,
46
Chris Craik1b54fb22015-06-02 17:40:58 -070047 SyncStart,
48 IssueDrawCommandsStart,
49 SwapBuffers,
50 FrameCompleted,
John Reckba6adf62015-02-19 14:36:50 -080051
John Reck2d5b8d72016-07-28 15:36:11 -070052 DequeueBufferDuration,
53 QueueBufferDuration,
54
Stan Iliev7203e1f2019-07-25 13:12:02 -040055 GpuCompleted,
56
John Reckba6adf62015-02-19 14:36:50 -080057 // Must be the last value!
John Reck65ddb152016-08-02 09:38:26 -070058 // Also must be kept in sync with FrameMetrics.java#FRAME_STATS_COUNT
Chris Craik1b54fb22015-06-02 17:40:58 -070059 NumIndexes
John Reckc87be992015-02-20 10:57:22 -080060};
John Reckba6adf62015-02-19 14:36:50 -080061
John Reck2a8bb052015-06-03 09:52:01 -070062extern const std::string FrameInfoNames[];
John Reck4db3d172015-06-02 15:58:43 -070063
Chris Craik1b54fb22015-06-02 17:40:58 -070064namespace FrameInfoFlags {
John Reck1bcacfd2017-11-03 10:12:19 -070065enum {
66 WindowLayoutChanged = 1 << 0,
67 RTAnimation = 1 << 1,
68 SurfaceCanvas = 1 << 2,
69 SkippedFrame = 1 << 3,
70};
John Reckc87be992015-02-20 10:57:22 -080071};
John Reckba6adf62015-02-19 14:36:50 -080072
Derek Sollenberger3fedf5a2020-02-21 13:07:28 -050073class UiFrameInfoBuilder {
John Reckba6adf62015-02-19 14:36:50 -080074public:
Steven Thomas6fabb5a2020-08-21 16:56:08 -070075 static constexpr int64_t INVALID_VSYNC_ID = -1;
76
Chih-Hung Hsiehfaecb782016-07-21 11:23:06 -070077 explicit UiFrameInfoBuilder(int64_t* buffer) : mBuffer(buffer) {
John Reckba6adf62015-02-19 14:36:50 -080078 memset(mBuffer, 0, UI_THREAD_FRAME_INFO_SIZE * sizeof(int64_t));
Steven Thomas6fabb5a2020-08-21 16:56:08 -070079 set(FrameInfoIndex::FrameTimelineVsyncId) = INVALID_VSYNC_ID;
John Reckba6adf62015-02-19 14:36:50 -080080 }
81
Steven Thomas6fabb5a2020-08-21 16:56:08 -070082 UiFrameInfoBuilder& setVsync(nsecs_t vsyncTime, nsecs_t intendedVsync, int64_t vsyncId) {
83 set(FrameInfoIndex::FrameTimelineVsyncId) = vsyncId;
Chris Craik1b54fb22015-06-02 17:40:58 -070084 set(FrameInfoIndex::Vsync) = vsyncTime;
85 set(FrameInfoIndex::IntendedVsync) = intendedVsync;
John Reckbf3c6022015-06-02 15:55:00 -070086 // Pretend the other fields are all at vsync, too, so that naive
87 // duration calculations end up being 0 instead of very large
Chris Craik1b54fb22015-06-02 17:40:58 -070088 set(FrameInfoIndex::HandleInputStart) = vsyncTime;
89 set(FrameInfoIndex::AnimationStart) = vsyncTime;
90 set(FrameInfoIndex::PerformTraversalsStart) = vsyncTime;
91 set(FrameInfoIndex::DrawStart) = vsyncTime;
John Reckba6adf62015-02-19 14:36:50 -080092 return *this;
93 }
94
Chris Craik1b54fb22015-06-02 17:40:58 -070095 UiFrameInfoBuilder& addFlag(int frameInfoFlag) {
96 set(FrameInfoIndex::Flags) |= static_cast<uint64_t>(frameInfoFlag);
John Reckba6adf62015-02-19 14:36:50 -080097 return *this;
98 }
99
100private:
John Reck1bcacfd2017-11-03 10:12:19 -0700101 inline int64_t& set(FrameInfoIndex index) { return mBuffer[static_cast<int>(index)]; }
John Reckc87be992015-02-20 10:57:22 -0800102
John Reckba6adf62015-02-19 14:36:50 -0800103 int64_t* mBuffer;
104};
105
106class FrameInfo {
107public:
108 void importUiThreadInfo(int64_t* info);
109
Jerome Gaillarde218c692019-06-14 12:58:57 +0100110 void markSyncStart() { set(FrameInfoIndex::SyncStart) = systemTime(SYSTEM_TIME_MONOTONIC); }
John Reckba6adf62015-02-19 14:36:50 -0800111
112 void markIssueDrawCommandsStart() {
Jerome Gaillarde218c692019-06-14 12:58:57 +0100113 set(FrameInfoIndex::IssueDrawCommandsStart) = systemTime(SYSTEM_TIME_MONOTONIC);
John Reckba6adf62015-02-19 14:36:50 -0800114 }
115
Jerome Gaillarde218c692019-06-14 12:58:57 +0100116 void markSwapBuffers() { set(FrameInfoIndex::SwapBuffers) = systemTime(SYSTEM_TIME_MONOTONIC); }
John Reckba6adf62015-02-19 14:36:50 -0800117
Jerome Gaillarde218c692019-06-14 12:58:57 +0100118 void markFrameCompleted() { set(FrameInfoIndex::FrameCompleted) = systemTime(SYSTEM_TIME_MONOTONIC); }
John Reckba6adf62015-02-19 14:36:50 -0800119
Chris Craik1b54fb22015-06-02 17:40:58 -0700120 void addFlag(int frameInfoFlag) {
121 set(FrameInfoIndex::Flags) |= static_cast<uint64_t>(frameInfoFlag);
John Reck240ff622015-04-28 13:50:00 -0700122 }
123
John Reck1bcacfd2017-11-03 10:12:19 -0700124 const int64_t* data() const { return mFrameInfo; }
Andres Morales06f5bc72015-12-15 15:21:31 -0800125
John Reck1bcacfd2017-11-03 10:12:19 -0700126 inline int64_t operator[](FrameInfoIndex index) const { return get(index); }
John Reckba6adf62015-02-19 14:36:50 -0800127
John Reck41300272015-06-03 14:42:34 -0700128 inline int64_t operator[](int index) const {
Chris Craik1b54fb22015-06-02 17:40:58 -0700129 if (index < 0 || index >= static_cast<int>(FrameInfoIndex::NumIndexes)) return 0;
John Reckc87be992015-02-20 10:57:22 -0800130 return mFrameInfo[index];
John Reckba6adf62015-02-19 14:36:50 -0800131 }
132
John Reck41300272015-06-03 14:42:34 -0700133 inline int64_t duration(FrameInfoIndex start, FrameInfoIndex end) const {
John Reckbe3fba02015-07-06 13:49:58 -0700134 int64_t endtime = get(end);
135 int64_t starttime = get(start);
John Reck41300272015-06-03 14:42:34 -0700136 int64_t gap = endtime - starttime;
137 gap = starttime > 0 ? gap : 0;
John Reck1bcacfd2017-11-03 10:12:19 -0700138 if (end > FrameInfoIndex::SyncQueued && start < FrameInfoIndex::SyncQueued) {
John Reckbe3fba02015-07-06 13:49:58 -0700139 // Need to subtract out the time spent in a stalled state
140 // as this will be captured by the previous frame's info
John Reck1bcacfd2017-11-03 10:12:19 -0700141 int64_t offset = get(FrameInfoIndex::SyncStart) - get(FrameInfoIndex::SyncQueued);
John Reckbe3fba02015-07-06 13:49:58 -0700142 if (offset > 0) {
143 gap -= offset;
144 }
145 }
John Reck41300272015-06-03 14:42:34 -0700146 return gap > 0 ? gap : 0;
147 }
148
149 inline int64_t totalDuration() const {
150 return duration(FrameInfoIndex::IntendedVsync, FrameInfoIndex::FrameCompleted);
151 }
152
Stan Iliev7203e1f2019-07-25 13:12:02 -0400153 inline int64_t gpuDrawTime() const {
154 // GPU start time is approximated to the moment before swapBuffer is invoked.
155 // We could add an EGLSyncKHR fence at the beginning of the frame, but that is an overhead.
156 int64_t endTime = get(FrameInfoIndex::GpuCompleted);
157 return endTime > 0 ? endTime - get(FrameInfoIndex::SwapBuffers) : -1;
158 }
159
John Reck1bcacfd2017-11-03 10:12:19 -0700160 inline int64_t& set(FrameInfoIndex index) { return mFrameInfo[static_cast<int>(index)]; }
John Reckc87be992015-02-20 10:57:22 -0800161
John Reckbe3fba02015-07-06 13:49:58 -0700162 inline int64_t get(FrameInfoIndex index) const {
163 if (index == FrameInfoIndex::NumIndexes) return 0;
164 return mFrameInfo[static_cast<int>(index)];
165 }
166
167private:
Chris Craik1b54fb22015-06-02 17:40:58 -0700168 int64_t mFrameInfo[static_cast<int>(FrameInfoIndex::NumIndexes)];
John Reckba6adf62015-02-19 14:36:50 -0800169};
170
171} /* namespace uirenderer */
172} /* namespace android */
173
174#endif /* FRAMEINFO_H_ */