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 27 namespace android { 28 namespace uirenderer { 29 30 #define UI_THREAD_FRAME_INFO_SIZE 9 31 32 enum 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 55 extern const std::string FrameInfoNames[]; 56 57 namespace FrameInfoFlags { 58 enum { 59 WindowLayoutChanged = 1 << 0, 60 RTAnimation = 1 << 1, 61 SurfaceCanvas = 1 << 2, 62 SkippedFrame = 1 << 3, 63 }; 64 }; 65 66 class ANDROID_API UiFrameInfoBuilder { 67 public: UiFrameInfoBuilder(int64_t * buffer)68 UiFrameInfoBuilder(int64_t* buffer) : mBuffer(buffer) { 69 memset(mBuffer, 0, UI_THREAD_FRAME_INFO_SIZE * sizeof(int64_t)); 70 } 71 setVsync(nsecs_t vsyncTime,nsecs_t intendedVsync)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 addFlag(int frameInfoFlag)84 UiFrameInfoBuilder& addFlag(int frameInfoFlag) { 85 set(FrameInfoIndex::Flags) |= static_cast<uint64_t>(frameInfoFlag); 86 return *this; 87 } 88 89 private: set(FrameInfoIndex index)90 inline int64_t& set(FrameInfoIndex index) { 91 return mBuffer[static_cast<int>(index)]; 92 } 93 94 int64_t* mBuffer; 95 }; 96 97 class FrameInfo { 98 public: 99 void importUiThreadInfo(int64_t* info); 100 markSyncStart()101 void markSyncStart() { 102 set(FrameInfoIndex::SyncStart) = systemTime(CLOCK_MONOTONIC); 103 } 104 markIssueDrawCommandsStart()105 void markIssueDrawCommandsStart() { 106 set(FrameInfoIndex::IssueDrawCommandsStart) = systemTime(CLOCK_MONOTONIC); 107 } 108 markSwapBuffers()109 void markSwapBuffers() { 110 set(FrameInfoIndex::SwapBuffers) = systemTime(CLOCK_MONOTONIC); 111 } 112 markFrameCompleted()113 void markFrameCompleted() { 114 set(FrameInfoIndex::FrameCompleted) = systemTime(CLOCK_MONOTONIC); 115 } 116 addFlag(int frameInfoFlag)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 duration(FrameInfoIndex start,FrameInfoIndex end)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 totalDuration()148 inline int64_t totalDuration() const { 149 return duration(FrameInfoIndex::IntendedVsync, FrameInfoIndex::FrameCompleted); 150 } 151 set(FrameInfoIndex index)152 inline int64_t& set(FrameInfoIndex index) { 153 return mFrameInfo[static_cast<int>(index)]; 154 } 155 get(FrameInfoIndex index)156 inline int64_t get(FrameInfoIndex index) const { 157 if (index == FrameInfoIndex::NumIndexes) return 0; 158 return mFrameInfo[static_cast<int>(index)]; 159 } 160 161 private: 162 int64_t mFrameInfo[static_cast<int>(FrameInfoIndex::NumIndexes)]; 163 }; 164 165 } /* namespace uirenderer */ 166 } /* namespace android */ 167 168 #endif /* FRAMEINFO_H_ */ 169