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 DequeueBufferDuration, 52 QueueBufferDuration, 53 54 // Must be the last value! 55 // Also must be kept in sync with FrameMetrics.java#FRAME_STATS_COUNT 56 NumIndexes 57 }; 58 59 extern const std::string FrameInfoNames[]; 60 61 namespace FrameInfoFlags { 62 enum { 63 WindowLayoutChanged = 1 << 0, 64 RTAnimation = 1 << 1, 65 SurfaceCanvas = 1 << 2, 66 SkippedFrame = 1 << 3, 67 }; 68 }; 69 70 class ANDROID_API UiFrameInfoBuilder { 71 public: UiFrameInfoBuilder(int64_t * buffer)72 explicit UiFrameInfoBuilder(int64_t* buffer) : mBuffer(buffer) { 73 memset(mBuffer, 0, UI_THREAD_FRAME_INFO_SIZE * sizeof(int64_t)); 74 } 75 setVsync(nsecs_t vsyncTime,nsecs_t intendedVsync)76 UiFrameInfoBuilder& setVsync(nsecs_t vsyncTime, nsecs_t intendedVsync) { 77 set(FrameInfoIndex::Vsync) = vsyncTime; 78 set(FrameInfoIndex::IntendedVsync) = intendedVsync; 79 // Pretend the other fields are all at vsync, too, so that naive 80 // duration calculations end up being 0 instead of very large 81 set(FrameInfoIndex::HandleInputStart) = vsyncTime; 82 set(FrameInfoIndex::AnimationStart) = vsyncTime; 83 set(FrameInfoIndex::PerformTraversalsStart) = vsyncTime; 84 set(FrameInfoIndex::DrawStart) = vsyncTime; 85 return *this; 86 } 87 addFlag(int frameInfoFlag)88 UiFrameInfoBuilder& addFlag(int frameInfoFlag) { 89 set(FrameInfoIndex::Flags) |= static_cast<uint64_t>(frameInfoFlag); 90 return *this; 91 } 92 93 private: set(FrameInfoIndex index)94 inline int64_t& set(FrameInfoIndex index) { return mBuffer[static_cast<int>(index)]; } 95 96 int64_t* mBuffer; 97 }; 98 99 class FrameInfo { 100 public: 101 void importUiThreadInfo(int64_t* info); 102 markSyncStart()103 void markSyncStart() { set(FrameInfoIndex::SyncStart) = systemTime(CLOCK_MONOTONIC); } 104 markIssueDrawCommandsStart()105 void markIssueDrawCommandsStart() { 106 set(FrameInfoIndex::IssueDrawCommandsStart) = systemTime(CLOCK_MONOTONIC); 107 } 108 markSwapBuffers()109 void markSwapBuffers() { set(FrameInfoIndex::SwapBuffers) = systemTime(CLOCK_MONOTONIC); } 110 markFrameCompleted()111 void markFrameCompleted() { set(FrameInfoIndex::FrameCompleted) = systemTime(CLOCK_MONOTONIC); } 112 addFlag(int frameInfoFlag)113 void addFlag(int frameInfoFlag) { 114 set(FrameInfoIndex::Flags) |= static_cast<uint64_t>(frameInfoFlag); 115 } 116 data()117 const int64_t* data() const { return mFrameInfo; } 118 119 inline int64_t operator[](FrameInfoIndex index) const { return get(index); } 120 121 inline int64_t operator[](int index) const { 122 if (index < 0 || index >= static_cast<int>(FrameInfoIndex::NumIndexes)) return 0; 123 return mFrameInfo[index]; 124 } 125 duration(FrameInfoIndex start,FrameInfoIndex end)126 inline int64_t duration(FrameInfoIndex start, FrameInfoIndex end) const { 127 int64_t endtime = get(end); 128 int64_t starttime = get(start); 129 int64_t gap = endtime - starttime; 130 gap = starttime > 0 ? gap : 0; 131 if (end > FrameInfoIndex::SyncQueued && start < FrameInfoIndex::SyncQueued) { 132 // Need to subtract out the time spent in a stalled state 133 // as this will be captured by the previous frame's info 134 int64_t offset = get(FrameInfoIndex::SyncStart) - get(FrameInfoIndex::SyncQueued); 135 if (offset > 0) { 136 gap -= offset; 137 } 138 } 139 return gap > 0 ? gap : 0; 140 } 141 totalDuration()142 inline int64_t totalDuration() const { 143 return duration(FrameInfoIndex::IntendedVsync, FrameInfoIndex::FrameCompleted); 144 } 145 set(FrameInfoIndex index)146 inline int64_t& set(FrameInfoIndex index) { return mFrameInfo[static_cast<int>(index)]; } 147 get(FrameInfoIndex index)148 inline int64_t get(FrameInfoIndex index) const { 149 if (index == FrameInfoIndex::NumIndexes) return 0; 150 return mFrameInfo[static_cast<int>(index)]; 151 } 152 153 private: 154 int64_t mFrameInfo[static_cast<int>(FrameInfoIndex::NumIndexes)]; 155 }; 156 157 } /* namespace uirenderer */ 158 } /* namespace android */ 159 160 #endif /* FRAMEINFO_H_ */ 161