xref: /aosp_15_r20/frameworks/base/libs/hwui/FrameInfo.h (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)
1*d57664e9SAndroid Build Coastguard Worker /*
2*d57664e9SAndroid Build Coastguard Worker  * Copyright (C) 2015 The Android Open Source Project
3*d57664e9SAndroid Build Coastguard Worker  *
4*d57664e9SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*d57664e9SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*d57664e9SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*d57664e9SAndroid Build Coastguard Worker  *
8*d57664e9SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*d57664e9SAndroid Build Coastguard Worker  *
10*d57664e9SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*d57664e9SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*d57664e9SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*d57664e9SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*d57664e9SAndroid Build Coastguard Worker  * limitations under the License.
15*d57664e9SAndroid Build Coastguard Worker  */
16*d57664e9SAndroid Build Coastguard Worker #ifndef FRAMEINFO_H_
17*d57664e9SAndroid Build Coastguard Worker #define FRAMEINFO_H_
18*d57664e9SAndroid Build Coastguard Worker 
19*d57664e9SAndroid Build Coastguard Worker #include <cutils/compiler.h>
20*d57664e9SAndroid Build Coastguard Worker #include <memory.h>
21*d57664e9SAndroid Build Coastguard Worker #include <utils/Timers.h>
22*d57664e9SAndroid Build Coastguard Worker 
23*d57664e9SAndroid Build Coastguard Worker #include <array>
24*d57664e9SAndroid Build Coastguard Worker #include <optional>
25*d57664e9SAndroid Build Coastguard Worker #include <string>
26*d57664e9SAndroid Build Coastguard Worker 
27*d57664e9SAndroid Build Coastguard Worker #include "SkippedFrameInfo.h"
28*d57664e9SAndroid Build Coastguard Worker #include "utils/Macros.h"
29*d57664e9SAndroid Build Coastguard Worker 
30*d57664e9SAndroid Build Coastguard Worker namespace android {
31*d57664e9SAndroid Build Coastguard Worker namespace uirenderer {
32*d57664e9SAndroid Build Coastguard Worker 
33*d57664e9SAndroid Build Coastguard Worker static constexpr size_t UI_THREAD_FRAME_INFO_SIZE = 12;
34*d57664e9SAndroid Build Coastguard Worker 
35*d57664e9SAndroid Build Coastguard Worker enum class FrameInfoIndex {
36*d57664e9SAndroid Build Coastguard Worker     Flags = 0,
37*d57664e9SAndroid Build Coastguard Worker     FrameTimelineVsyncId,
38*d57664e9SAndroid Build Coastguard Worker     IntendedVsync,
39*d57664e9SAndroid Build Coastguard Worker     Vsync,
40*d57664e9SAndroid Build Coastguard Worker     InputEventId,
41*d57664e9SAndroid Build Coastguard Worker     HandleInputStart,
42*d57664e9SAndroid Build Coastguard Worker     AnimationStart,
43*d57664e9SAndroid Build Coastguard Worker     PerformTraversalsStart,
44*d57664e9SAndroid Build Coastguard Worker     DrawStart,
45*d57664e9SAndroid Build Coastguard Worker     FrameDeadline,
46*d57664e9SAndroid Build Coastguard Worker     FrameStartTime,
47*d57664e9SAndroid Build Coastguard Worker     FrameInterval,
48*d57664e9SAndroid Build Coastguard Worker     // End of UI frame info
49*d57664e9SAndroid Build Coastguard Worker 
50*d57664e9SAndroid Build Coastguard Worker     SyncQueued,
51*d57664e9SAndroid Build Coastguard Worker 
52*d57664e9SAndroid Build Coastguard Worker     SyncStart,
53*d57664e9SAndroid Build Coastguard Worker     IssueDrawCommandsStart,
54*d57664e9SAndroid Build Coastguard Worker     SwapBuffers,
55*d57664e9SAndroid Build Coastguard Worker     FrameCompleted,
56*d57664e9SAndroid Build Coastguard Worker 
57*d57664e9SAndroid Build Coastguard Worker     DequeueBufferDuration,
58*d57664e9SAndroid Build Coastguard Worker     QueueBufferDuration,
59*d57664e9SAndroid Build Coastguard Worker 
60*d57664e9SAndroid Build Coastguard Worker     GpuCompleted,
61*d57664e9SAndroid Build Coastguard Worker     SwapBuffersCompleted,
62*d57664e9SAndroid Build Coastguard Worker     DisplayPresentTime,
63*d57664e9SAndroid Build Coastguard Worker     CommandSubmissionCompleted,
64*d57664e9SAndroid Build Coastguard Worker 
65*d57664e9SAndroid Build Coastguard Worker     // Must be the last value!
66*d57664e9SAndroid Build Coastguard Worker     // Also must be kept in sync with FrameMetrics.java#FRAME_STATS_COUNT
67*d57664e9SAndroid Build Coastguard Worker     NumIndexes
68*d57664e9SAndroid Build Coastguard Worker };
69*d57664e9SAndroid Build Coastguard Worker 
70*d57664e9SAndroid Build Coastguard Worker extern const std::array<const char*, static_cast<int>(FrameInfoIndex::NumIndexes)> FrameInfoNames;
71*d57664e9SAndroid Build Coastguard Worker 
72*d57664e9SAndroid Build Coastguard Worker namespace FrameInfoFlags {
73*d57664e9SAndroid Build Coastguard Worker enum {
74*d57664e9SAndroid Build Coastguard Worker     WindowVisibilityChanged = 1 << 0,
75*d57664e9SAndroid Build Coastguard Worker     RTAnimation = 1 << 1,
76*d57664e9SAndroid Build Coastguard Worker     SurfaceCanvas = 1 << 2,
77*d57664e9SAndroid Build Coastguard Worker     SkippedFrame = 1 << 3,
78*d57664e9SAndroid Build Coastguard Worker };
79*d57664e9SAndroid Build Coastguard Worker };
80*d57664e9SAndroid Build Coastguard Worker 
81*d57664e9SAndroid Build Coastguard Worker class UiFrameInfoBuilder {
82*d57664e9SAndroid Build Coastguard Worker public:
83*d57664e9SAndroid Build Coastguard Worker     static constexpr int64_t INVALID_VSYNC_ID = -1;
84*d57664e9SAndroid Build Coastguard Worker     static constexpr int64_t UNKNOWN_DEADLINE = std::numeric_limits<int64_t>::max();
85*d57664e9SAndroid Build Coastguard Worker     static constexpr int64_t UNKNOWN_FRAME_INTERVAL = -1;
86*d57664e9SAndroid Build Coastguard Worker 
87*d57664e9SAndroid Build Coastguard Worker 
UiFrameInfoBuilder(int64_t * buffer)88*d57664e9SAndroid Build Coastguard Worker     explicit UiFrameInfoBuilder(int64_t* buffer) : mBuffer(buffer) {
89*d57664e9SAndroid Build Coastguard Worker         memset(mBuffer, 0, UI_THREAD_FRAME_INFO_SIZE * sizeof(int64_t));
90*d57664e9SAndroid Build Coastguard Worker         set(FrameInfoIndex::FrameTimelineVsyncId) = INVALID_VSYNC_ID;
91*d57664e9SAndroid Build Coastguard Worker         // The struct is zeroed by memset above. That also sets FrameInfoIndex::InputEventId to
92*d57664e9SAndroid Build Coastguard Worker         // equal android::os::IInputConstants::INVALID_INPUT_EVENT_ID == 0.
93*d57664e9SAndroid Build Coastguard Worker         // Therefore, we can skip setting the value for InputEventId here. If the value for
94*d57664e9SAndroid Build Coastguard Worker         // INVALID_INPUT_EVENT_ID changes, this code would have to be updated, as well.
95*d57664e9SAndroid Build Coastguard Worker         set(FrameInfoIndex::FrameDeadline) = std::numeric_limits<int64_t>::max();
96*d57664e9SAndroid Build Coastguard Worker     }
97*d57664e9SAndroid Build Coastguard Worker 
setVsync(nsecs_t vsyncTime,nsecs_t intendedVsync,int64_t vsyncId,int64_t frameDeadline,nsecs_t frameInterval)98*d57664e9SAndroid Build Coastguard Worker     UiFrameInfoBuilder& setVsync(nsecs_t vsyncTime, nsecs_t intendedVsync,
99*d57664e9SAndroid Build Coastguard Worker                                  int64_t vsyncId, int64_t frameDeadline, nsecs_t frameInterval) {
100*d57664e9SAndroid Build Coastguard Worker         set(FrameInfoIndex::FrameTimelineVsyncId) = vsyncId;
101*d57664e9SAndroid Build Coastguard Worker         set(FrameInfoIndex::Vsync) = vsyncTime;
102*d57664e9SAndroid Build Coastguard Worker         set(FrameInfoIndex::IntendedVsync) = intendedVsync;
103*d57664e9SAndroid Build Coastguard Worker         // Pretend the other fields are all at vsync, too, so that naive
104*d57664e9SAndroid Build Coastguard Worker         // duration calculations end up being 0 instead of very large
105*d57664e9SAndroid Build Coastguard Worker         set(FrameInfoIndex::HandleInputStart) = vsyncTime;
106*d57664e9SAndroid Build Coastguard Worker         set(FrameInfoIndex::AnimationStart) = vsyncTime;
107*d57664e9SAndroid Build Coastguard Worker         set(FrameInfoIndex::PerformTraversalsStart) = vsyncTime;
108*d57664e9SAndroid Build Coastguard Worker         set(FrameInfoIndex::DrawStart) = vsyncTime;
109*d57664e9SAndroid Build Coastguard Worker         set(FrameInfoIndex::FrameStartTime) = vsyncTime;
110*d57664e9SAndroid Build Coastguard Worker         set(FrameInfoIndex::FrameDeadline) = frameDeadline;
111*d57664e9SAndroid Build Coastguard Worker         set(FrameInfoIndex::FrameInterval) = frameInterval;
112*d57664e9SAndroid Build Coastguard Worker         return *this;
113*d57664e9SAndroid Build Coastguard Worker     }
114*d57664e9SAndroid Build Coastguard Worker 
addFlag(int frameInfoFlag)115*d57664e9SAndroid Build Coastguard Worker     UiFrameInfoBuilder& addFlag(int frameInfoFlag) {
116*d57664e9SAndroid Build Coastguard Worker         set(FrameInfoIndex::Flags) |= static_cast<uint64_t>(frameInfoFlag);
117*d57664e9SAndroid Build Coastguard Worker         return *this;
118*d57664e9SAndroid Build Coastguard Worker     }
119*d57664e9SAndroid Build Coastguard Worker 
120*d57664e9SAndroid Build Coastguard Worker private:
set(FrameInfoIndex index)121*d57664e9SAndroid Build Coastguard Worker     inline int64_t& set(FrameInfoIndex index) { return mBuffer[static_cast<int>(index)]; }
122*d57664e9SAndroid Build Coastguard Worker 
123*d57664e9SAndroid Build Coastguard Worker     int64_t* mBuffer;
124*d57664e9SAndroid Build Coastguard Worker };
125*d57664e9SAndroid Build Coastguard Worker 
126*d57664e9SAndroid Build Coastguard Worker class FrameInfo {
127*d57664e9SAndroid Build Coastguard Worker public:
128*d57664e9SAndroid Build Coastguard Worker     void importUiThreadInfo(int64_t* info);
129*d57664e9SAndroid Build Coastguard Worker 
markSyncStart()130*d57664e9SAndroid Build Coastguard Worker     void markSyncStart() { set(FrameInfoIndex::SyncStart) = systemTime(SYSTEM_TIME_MONOTONIC); }
131*d57664e9SAndroid Build Coastguard Worker 
markIssueDrawCommandsStart()132*d57664e9SAndroid Build Coastguard Worker     void markIssueDrawCommandsStart() {
133*d57664e9SAndroid Build Coastguard Worker         set(FrameInfoIndex::IssueDrawCommandsStart) = systemTime(SYSTEM_TIME_MONOTONIC);
134*d57664e9SAndroid Build Coastguard Worker     }
135*d57664e9SAndroid Build Coastguard Worker 
markSwapBuffers()136*d57664e9SAndroid Build Coastguard Worker     void markSwapBuffers() { set(FrameInfoIndex::SwapBuffers) = systemTime(SYSTEM_TIME_MONOTONIC); }
137*d57664e9SAndroid Build Coastguard Worker 
markSwapBuffersCompleted()138*d57664e9SAndroid Build Coastguard Worker     void markSwapBuffersCompleted() {
139*d57664e9SAndroid Build Coastguard Worker         set(FrameInfoIndex::SwapBuffersCompleted) = systemTime(SYSTEM_TIME_MONOTONIC);
140*d57664e9SAndroid Build Coastguard Worker     }
141*d57664e9SAndroid Build Coastguard Worker 
markFrameCompleted()142*d57664e9SAndroid Build Coastguard Worker     void markFrameCompleted() { set(FrameInfoIndex::FrameCompleted) = systemTime(SYSTEM_TIME_MONOTONIC); }
143*d57664e9SAndroid Build Coastguard Worker 
addFlag(int frameInfoFlag)144*d57664e9SAndroid Build Coastguard Worker     void addFlag(int frameInfoFlag) {
145*d57664e9SAndroid Build Coastguard Worker         set(FrameInfoIndex::Flags) |= static_cast<uint64_t>(frameInfoFlag);
146*d57664e9SAndroid Build Coastguard Worker     }
147*d57664e9SAndroid Build Coastguard Worker 
data()148*d57664e9SAndroid Build Coastguard Worker     const int64_t* data() const { return mFrameInfo; }
149*d57664e9SAndroid Build Coastguard Worker 
150*d57664e9SAndroid Build Coastguard Worker     inline int64_t operator[](FrameInfoIndex index) const { return get(index); }
151*d57664e9SAndroid Build Coastguard Worker 
152*d57664e9SAndroid Build Coastguard Worker     inline int64_t operator[](int index) const {
153*d57664e9SAndroid Build Coastguard Worker         if (index < 0 || index >= static_cast<int>(FrameInfoIndex::NumIndexes)) return 0;
154*d57664e9SAndroid Build Coastguard Worker         return mFrameInfo[index];
155*d57664e9SAndroid Build Coastguard Worker     }
156*d57664e9SAndroid Build Coastguard Worker 
duration(FrameInfoIndex start,FrameInfoIndex end)157*d57664e9SAndroid Build Coastguard Worker     inline int64_t duration(FrameInfoIndex start, FrameInfoIndex end) const {
158*d57664e9SAndroid Build Coastguard Worker         int64_t endtime = get(end);
159*d57664e9SAndroid Build Coastguard Worker         int64_t starttime = get(start);
160*d57664e9SAndroid Build Coastguard Worker         int64_t gap = endtime - starttime;
161*d57664e9SAndroid Build Coastguard Worker         gap = starttime > 0 ? gap : 0;
162*d57664e9SAndroid Build Coastguard Worker         if (end > FrameInfoIndex::SyncQueued && start < FrameInfoIndex::SyncQueued) {
163*d57664e9SAndroid Build Coastguard Worker             // Need to subtract out the time spent in a stalled state
164*d57664e9SAndroid Build Coastguard Worker             // as this will be captured by the previous frame's info
165*d57664e9SAndroid Build Coastguard Worker             int64_t offset = get(FrameInfoIndex::SyncStart) - get(FrameInfoIndex::SyncQueued);
166*d57664e9SAndroid Build Coastguard Worker             if (offset > 0) {
167*d57664e9SAndroid Build Coastguard Worker                 gap -= offset;
168*d57664e9SAndroid Build Coastguard Worker             }
169*d57664e9SAndroid Build Coastguard Worker         }
170*d57664e9SAndroid Build Coastguard Worker         return gap > 0 ? gap : 0;
171*d57664e9SAndroid Build Coastguard Worker     }
172*d57664e9SAndroid Build Coastguard Worker 
totalDuration()173*d57664e9SAndroid Build Coastguard Worker     inline int64_t totalDuration() const {
174*d57664e9SAndroid Build Coastguard Worker         return duration(FrameInfoIndex::IntendedVsync, FrameInfoIndex::FrameCompleted);
175*d57664e9SAndroid Build Coastguard Worker     }
176*d57664e9SAndroid Build Coastguard Worker 
gpuDrawTime()177*d57664e9SAndroid Build Coastguard Worker     inline int64_t gpuDrawTime() const {
178*d57664e9SAndroid Build Coastguard Worker         // GPU start time is approximated to the moment before swapBuffer is invoked.
179*d57664e9SAndroid Build Coastguard Worker         // We could add an EGLSyncKHR fence at the beginning of the frame, but that is an overhead.
180*d57664e9SAndroid Build Coastguard Worker         int64_t endTime = get(FrameInfoIndex::GpuCompleted);
181*d57664e9SAndroid Build Coastguard Worker         return endTime > 0 ? endTime - get(FrameInfoIndex::SwapBuffers) : -1;
182*d57664e9SAndroid Build Coastguard Worker     }
183*d57664e9SAndroid Build Coastguard Worker 
set(FrameInfoIndex index)184*d57664e9SAndroid Build Coastguard Worker     inline int64_t& set(FrameInfoIndex index) { return mFrameInfo[static_cast<int>(index)]; }
185*d57664e9SAndroid Build Coastguard Worker 
get(FrameInfoIndex index)186*d57664e9SAndroid Build Coastguard Worker     inline int64_t get(FrameInfoIndex index) const {
187*d57664e9SAndroid Build Coastguard Worker         if (index == FrameInfoIndex::NumIndexes) return 0;
188*d57664e9SAndroid Build Coastguard Worker         return mFrameInfo[static_cast<int>(index)];
189*d57664e9SAndroid Build Coastguard Worker     }
190*d57664e9SAndroid Build Coastguard Worker 
191*d57664e9SAndroid Build Coastguard Worker     void setSkippedFrameReason(SkippedFrameReason reason);
getSkippedFrameReason()192*d57664e9SAndroid Build Coastguard Worker     inline std::optional<SkippedFrameReason> getSkippedFrameReason() const {
193*d57664e9SAndroid Build Coastguard Worker         return mSkippedFrameReason;
194*d57664e9SAndroid Build Coastguard Worker     }
195*d57664e9SAndroid Build Coastguard Worker 
196*d57664e9SAndroid Build Coastguard Worker private:
197*d57664e9SAndroid Build Coastguard Worker     int64_t mFrameInfo[static_cast<int>(FrameInfoIndex::NumIndexes)];
198*d57664e9SAndroid Build Coastguard Worker     std::optional<SkippedFrameReason> mSkippedFrameReason;
199*d57664e9SAndroid Build Coastguard Worker };
200*d57664e9SAndroid Build Coastguard Worker 
201*d57664e9SAndroid Build Coastguard Worker } /* namespace uirenderer */
202*d57664e9SAndroid Build Coastguard Worker } /* namespace android */
203*d57664e9SAndroid Build Coastguard Worker 
204*d57664e9SAndroid Build Coastguard Worker #endif /* FRAMEINFO_H_ */
205