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