blob: f7ad13978a305ede56d9db3e8211e4e313f3e137 [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
John Reckba6adf62015-02-19 14:36:50 -080019#include <cutils/compiler.h>
Ady Abrahame088dcd2023-08-10 11:45:58 -070020#include <memory.h>
John Reckba6adf62015-02-19 14:36:50 -080021#include <utils/Timers.h>
22
Siarhei Vishniakouefed1662020-11-30 10:30:52 -100023#include <array>
Ady Abrahame088dcd2023-08-10 11:45:58 -070024#include <optional>
John Reck4db3d172015-06-02 15:58:43 -070025#include <string>
John Reckba6adf62015-02-19 14:36:50 -080026
Ady Abrahame088dcd2023-08-10 11:45:58 -070027#include "SkippedFrameInfo.h"
28#include "utils/Macros.h"
29
John Reckba6adf62015-02-19 14:36:50 -080030namespace android {
31namespace uirenderer {
32
Jorim Jaggi10f328c2021-01-19 00:08:02 +010033static constexpr size_t UI_THREAD_FRAME_INFO_SIZE = 12;
John Reckba6adf62015-02-19 14:36:50 -080034
John Reckc87be992015-02-20 10:57:22 -080035enum class FrameInfoIndex {
Chris Craik1b54fb22015-06-02 17:40:58 -070036 Flags = 0,
Steven Thomas6fabb5a2020-08-21 16:56:08 -070037 FrameTimelineVsyncId,
Chris Craik1b54fb22015-06-02 17:40:58 -070038 IntendedVsync,
39 Vsync,
Siarhei Vishniakou4bcbffd2021-02-17 06:19:36 +000040 InputEventId,
Chris Craik1b54fb22015-06-02 17:40:58 -070041 HandleInputStart,
42 AnimationStart,
43 PerformTraversalsStart,
44 DrawStart,
Ady Abrahamdfb13982020-10-05 17:59:09 -070045 FrameDeadline,
Bo Liu027b2182021-03-18 16:50:38 -040046 FrameStartTime,
Jorim Jaggi10f328c2021-01-19 00:08:02 +010047 FrameInterval,
John Reckba6adf62015-02-19 14:36:50 -080048 // End of UI frame info
49
John Reckbe3fba02015-07-06 13:49:58 -070050 SyncQueued,
51
Chris Craik1b54fb22015-06-02 17:40:58 -070052 SyncStart,
53 IssueDrawCommandsStart,
54 SwapBuffers,
55 FrameCompleted,
John Reckba6adf62015-02-19 14:36:50 -080056
John Reck2d5b8d72016-07-28 15:36:11 -070057 DequeueBufferDuration,
58 QueueBufferDuration,
59
Stan Iliev7203e1f2019-07-25 13:12:02 -040060 GpuCompleted,
Jorim Jaggi71db8892021-02-03 23:19:29 +010061 SwapBuffersCompleted,
Siarhei Vishniakou4bcbffd2021-02-17 06:19:36 +000062 DisplayPresentTime,
Alec Mouri3afb3972022-05-27 22:03:11 +000063 CommandSubmissionCompleted,
Stan Iliev7203e1f2019-07-25 13:12:02 -040064
John Reckba6adf62015-02-19 14:36:50 -080065 // Must be the last value!
John Reck65ddb152016-08-02 09:38:26 -070066 // Also must be kept in sync with FrameMetrics.java#FRAME_STATS_COUNT
Chris Craik1b54fb22015-06-02 17:40:58 -070067 NumIndexes
John Reckc87be992015-02-20 10:57:22 -080068};
John Reckba6adf62015-02-19 14:36:50 -080069
Siarhei Vishniakou4bcbffd2021-02-17 06:19:36 +000070extern const std::array<const char*, static_cast<int>(FrameInfoIndex::NumIndexes)> FrameInfoNames;
John Reck4db3d172015-06-02 15:58:43 -070071
Chris Craik1b54fb22015-06-02 17:40:58 -070072namespace FrameInfoFlags {
John Reck1bcacfd2017-11-03 10:12:19 -070073enum {
Jorim Jaggi95166052021-05-03 15:49:25 +020074 WindowVisibilityChanged = 1 << 0,
John Reck1bcacfd2017-11-03 10:12:19 -070075 RTAnimation = 1 << 1,
76 SurfaceCanvas = 1 << 2,
77 SkippedFrame = 1 << 3,
78};
John Reckc87be992015-02-20 10:57:22 -080079};
John Reckba6adf62015-02-19 14:36:50 -080080
Derek Sollenberger3fedf5a2020-02-21 13:07:28 -050081class UiFrameInfoBuilder {
John Reckba6adf62015-02-19 14:36:50 -080082public:
Steven Thomas6fabb5a2020-08-21 16:56:08 -070083 static constexpr int64_t INVALID_VSYNC_ID = -1;
Jorim Jaggi10f328c2021-01-19 00:08:02 +010084 static constexpr int64_t UNKNOWN_DEADLINE = std::numeric_limits<int64_t>::max();
85 static constexpr int64_t UNKNOWN_FRAME_INTERVAL = -1;
86
Steven Thomas6fabb5a2020-08-21 16:56:08 -070087
Chih-Hung Hsiehfaecb782016-07-21 11:23:06 -070088 explicit UiFrameInfoBuilder(int64_t* buffer) : mBuffer(buffer) {
John Reckba6adf62015-02-19 14:36:50 -080089 memset(mBuffer, 0, UI_THREAD_FRAME_INFO_SIZE * sizeof(int64_t));
Steven Thomas6fabb5a2020-08-21 16:56:08 -070090 set(FrameInfoIndex::FrameTimelineVsyncId) = INVALID_VSYNC_ID;
Siarhei Vishniakoudca19462021-02-27 08:38:31 +000091 // The struct is zeroed by memset above. That also sets FrameInfoIndex::InputEventId to
92 // equal android::os::IInputConstants::INVALID_INPUT_EVENT_ID == 0.
93 // Therefore, we can skip setting the value for InputEventId here. If the value for
94 // INVALID_INPUT_EVENT_ID changes, this code would have to be updated, as well.
Ady Abrahamdfb13982020-10-05 17:59:09 -070095 set(FrameInfoIndex::FrameDeadline) = std::numeric_limits<int64_t>::max();
John Reckba6adf62015-02-19 14:36:50 -080096 }
97
Ady Abrahamdfb13982020-10-05 17:59:09 -070098 UiFrameInfoBuilder& setVsync(nsecs_t vsyncTime, nsecs_t intendedVsync,
Jorim Jaggi10f328c2021-01-19 00:08:02 +010099 int64_t vsyncId, int64_t frameDeadline, nsecs_t frameInterval) {
Steven Thomas6fabb5a2020-08-21 16:56:08 -0700100 set(FrameInfoIndex::FrameTimelineVsyncId) = vsyncId;
Chris Craik1b54fb22015-06-02 17:40:58 -0700101 set(FrameInfoIndex::Vsync) = vsyncTime;
102 set(FrameInfoIndex::IntendedVsync) = intendedVsync;
John Reckbf3c6022015-06-02 15:55:00 -0700103 // Pretend the other fields are all at vsync, too, so that naive
104 // duration calculations end up being 0 instead of very large
Chris Craik1b54fb22015-06-02 17:40:58 -0700105 set(FrameInfoIndex::HandleInputStart) = vsyncTime;
106 set(FrameInfoIndex::AnimationStart) = vsyncTime;
107 set(FrameInfoIndex::PerformTraversalsStart) = vsyncTime;
108 set(FrameInfoIndex::DrawStart) = vsyncTime;
Matt Buckleye9023cf2022-11-23 22:39:25 +0000109 set(FrameInfoIndex::FrameStartTime) = vsyncTime;
Ady Abrahamdfb13982020-10-05 17:59:09 -0700110 set(FrameInfoIndex::FrameDeadline) = frameDeadline;
Jorim Jaggi10f328c2021-01-19 00:08:02 +0100111 set(FrameInfoIndex::FrameInterval) = frameInterval;
John Reckba6adf62015-02-19 14:36:50 -0800112 return *this;
113 }
114
Chris Craik1b54fb22015-06-02 17:40:58 -0700115 UiFrameInfoBuilder& addFlag(int frameInfoFlag) {
116 set(FrameInfoIndex::Flags) |= static_cast<uint64_t>(frameInfoFlag);
John Reckba6adf62015-02-19 14:36:50 -0800117 return *this;
118 }
119
120private:
John Reck1bcacfd2017-11-03 10:12:19 -0700121 inline int64_t& set(FrameInfoIndex index) { return mBuffer[static_cast<int>(index)]; }
John Reckc87be992015-02-20 10:57:22 -0800122
John Reckba6adf62015-02-19 14:36:50 -0800123 int64_t* mBuffer;
124};
125
126class FrameInfo {
127public:
128 void importUiThreadInfo(int64_t* info);
129
Jerome Gaillarde218c692019-06-14 12:58:57 +0100130 void markSyncStart() { set(FrameInfoIndex::SyncStart) = systemTime(SYSTEM_TIME_MONOTONIC); }
John Reckba6adf62015-02-19 14:36:50 -0800131
132 void markIssueDrawCommandsStart() {
Jerome Gaillarde218c692019-06-14 12:58:57 +0100133 set(FrameInfoIndex::IssueDrawCommandsStart) = systemTime(SYSTEM_TIME_MONOTONIC);
John Reckba6adf62015-02-19 14:36:50 -0800134 }
135
Jerome Gaillarde218c692019-06-14 12:58:57 +0100136 void markSwapBuffers() { set(FrameInfoIndex::SwapBuffers) = systemTime(SYSTEM_TIME_MONOTONIC); }
John Reckba6adf62015-02-19 14:36:50 -0800137
Jorim Jaggi71db8892021-02-03 23:19:29 +0100138 void markSwapBuffersCompleted() {
139 set(FrameInfoIndex::SwapBuffersCompleted) = systemTime(SYSTEM_TIME_MONOTONIC);
140 }
141
Jerome Gaillarde218c692019-06-14 12:58:57 +0100142 void markFrameCompleted() { set(FrameInfoIndex::FrameCompleted) = systemTime(SYSTEM_TIME_MONOTONIC); }
John Reckba6adf62015-02-19 14:36:50 -0800143
Chris Craik1b54fb22015-06-02 17:40:58 -0700144 void addFlag(int frameInfoFlag) {
145 set(FrameInfoIndex::Flags) |= static_cast<uint64_t>(frameInfoFlag);
John Reck240ff622015-04-28 13:50:00 -0700146 }
147
John Reck1bcacfd2017-11-03 10:12:19 -0700148 const int64_t* data() const { return mFrameInfo; }
Andres Morales06f5bc72015-12-15 15:21:31 -0800149
John Reck1bcacfd2017-11-03 10:12:19 -0700150 inline int64_t operator[](FrameInfoIndex index) const { return get(index); }
John Reckba6adf62015-02-19 14:36:50 -0800151
John Reck41300272015-06-03 14:42:34 -0700152 inline int64_t operator[](int index) const {
Chris Craik1b54fb22015-06-02 17:40:58 -0700153 if (index < 0 || index >= static_cast<int>(FrameInfoIndex::NumIndexes)) return 0;
John Reckc87be992015-02-20 10:57:22 -0800154 return mFrameInfo[index];
John Reckba6adf62015-02-19 14:36:50 -0800155 }
156
John Reck41300272015-06-03 14:42:34 -0700157 inline int64_t duration(FrameInfoIndex start, FrameInfoIndex end) const {
John Reckbe3fba02015-07-06 13:49:58 -0700158 int64_t endtime = get(end);
159 int64_t starttime = get(start);
John Reck41300272015-06-03 14:42:34 -0700160 int64_t gap = endtime - starttime;
161 gap = starttime > 0 ? gap : 0;
John Reck1bcacfd2017-11-03 10:12:19 -0700162 if (end > FrameInfoIndex::SyncQueued && start < FrameInfoIndex::SyncQueued) {
John Reckbe3fba02015-07-06 13:49:58 -0700163 // Need to subtract out the time spent in a stalled state
164 // as this will be captured by the previous frame's info
John Reck1bcacfd2017-11-03 10:12:19 -0700165 int64_t offset = get(FrameInfoIndex::SyncStart) - get(FrameInfoIndex::SyncQueued);
John Reckbe3fba02015-07-06 13:49:58 -0700166 if (offset > 0) {
167 gap -= offset;
168 }
169 }
John Reck41300272015-06-03 14:42:34 -0700170 return gap > 0 ? gap : 0;
171 }
172
173 inline int64_t totalDuration() const {
174 return duration(FrameInfoIndex::IntendedVsync, FrameInfoIndex::FrameCompleted);
175 }
176
Stan Iliev7203e1f2019-07-25 13:12:02 -0400177 inline int64_t gpuDrawTime() const {
178 // GPU start time is approximated to the moment before swapBuffer is invoked.
179 // We could add an EGLSyncKHR fence at the beginning of the frame, but that is an overhead.
180 int64_t endTime = get(FrameInfoIndex::GpuCompleted);
Boleyn Sua9ce6622020-11-18 03:15:29 +0000181 return endTime > 0 ? endTime - get(FrameInfoIndex::SwapBuffers) : -1;
Stan Iliev7203e1f2019-07-25 13:12:02 -0400182 }
183
John Reck1bcacfd2017-11-03 10:12:19 -0700184 inline int64_t& set(FrameInfoIndex index) { return mFrameInfo[static_cast<int>(index)]; }
John Reckc87be992015-02-20 10:57:22 -0800185
John Reckbe3fba02015-07-06 13:49:58 -0700186 inline int64_t get(FrameInfoIndex index) const {
187 if (index == FrameInfoIndex::NumIndexes) return 0;
188 return mFrameInfo[static_cast<int>(index)];
189 }
190
Ady Abrahame088dcd2023-08-10 11:45:58 -0700191 void setSkippedFrameReason(SkippedFrameReason reason);
192 inline std::optional<SkippedFrameReason> getSkippedFrameReason() const {
193 return mSkippedFrameReason;
194 }
195
John Reckbe3fba02015-07-06 13:49:58 -0700196private:
Chris Craik1b54fb22015-06-02 17:40:58 -0700197 int64_t mFrameInfo[static_cast<int>(FrameInfoIndex::NumIndexes)];
Ady Abrahame088dcd2023-08-10 11:45:58 -0700198 std::optional<SkippedFrameReason> mSkippedFrameReason;
John Reckba6adf62015-02-19 14:36:50 -0800199};
200
201} /* namespace uirenderer */
202} /* namespace android */
203
204#endif /* FRAMEINFO_H_ */