blob: a919911988a3d5512f9a8e69740474de6ce008ad [file] [log] [blame]
Brian Andersond6927fb2016-07-23 23:37:30 -07001/*
2* Copyright 2016 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
17#include <gui/FrameTimestamps.h>
18
19#include <inttypes.h>
20#include <utils/String8.h>
21
22#include <algorithm>
23#include <limits>
24
25namespace android {
26
27static inline bool isValidTimestamp(nsecs_t time) {
28 return time > 0 && time < INT64_MAX;
29}
30
31// ============================================================================
32// FrameTimestamps
33// ============================================================================
34
35FrameTimestamps::FrameTimestamps(const FrameEvents& events) :
36 frameNumber(events.frameNumber),
37 postedTime(events.postedTime),
38 requestedPresentTime(events.requestedPresentTime),
39 acquireTime(events.acquireTime),
40 refreshStartTime(events.firstRefreshStartTime),
41 glCompositionDoneTime(events.gpuCompositionDoneTime),
42 displayPresentTime(events.displayPresentTime),
43 displayRetireTime(events.displayRetireTime),
44 releaseTime(events.releaseTime) {}
45
46
47// ============================================================================
48// FrameEvents
49// ============================================================================
50
51static void checkFenceForCompletion(sp<Fence>* fence, nsecs_t* dstTime) {
52 if ((*fence)->isValid()) {
53 nsecs_t time = (*fence)->getSignalTime();
54 if (isValidTimestamp(time)) {
55 *dstTime = time;
56 *fence = Fence::NO_FENCE;
57 }
58 }
59}
60
61void FrameEvents::checkFencesForCompletion() {
62 checkFenceForCompletion(&acquireFence, &acquireTime);
63 checkFenceForCompletion(&gpuCompositionDoneFence, &gpuCompositionDoneTime);
64 checkFenceForCompletion(&displayPresentFence, &displayPresentTime);
65 checkFenceForCompletion(&displayRetireFence, &displayRetireTime);
66 checkFenceForCompletion(&releaseFence, &releaseTime);
67}
68
69void FrameEvents::dump(String8& outString) const
70{
71 if (!valid) {
72 return;
73 }
74
75 outString.appendFormat("-- Frame %" PRIu64 "\n", frameNumber);
76 outString.appendFormat("--- Posted \t%" PRId64 "\n", postedTime);
77 outString.appendFormat("--- Req. Present\t%" PRId64 "\n", requestedPresentTime);
78
79 outString.appendFormat("--- Latched \t");
80 if (isValidTimestamp(latchTime)) {
81 outString.appendFormat("%" PRId64 "\n", latchTime);
82 } else {
83 outString.appendFormat("Pending\n");
84 }
85
86 outString.appendFormat("--- Refresh (First)\t");
87 if (isValidTimestamp(firstRefreshStartTime)) {
88 outString.appendFormat("%" PRId64 "\n", firstRefreshStartTime);
89 } else {
90 outString.appendFormat("Pending\n");
91 }
92
93 outString.appendFormat("--- Refresh (Last)\t");
94 if (isValidTimestamp(lastRefreshStartTime)) {
95 outString.appendFormat("%" PRId64 "\n", lastRefreshStartTime);
96 } else {
97 outString.appendFormat("Pending\n");
98 }
99
100 outString.appendFormat("--- Acquire \t");
101 if (isValidTimestamp(acquireTime)) {
102 outString.appendFormat("%" PRId64 "\n", acquireTime);
103 } else {
104 outString.appendFormat("Pending\n");
105 }
106
107 outString.appendFormat("--- GPU Composite Done\t");
108 if (isValidTimestamp(gpuCompositionDoneTime)) {
109 outString.appendFormat("%" PRId64 "\n", gpuCompositionDoneTime);
110 } else if (!addPostCompositeCalled || gpuCompositionDoneFence->isValid()) {
111 outString.appendFormat("Pending\n");
112 } else {
113 outString.appendFormat("N/A\n");
114 }
115
116 outString.appendFormat("--- Display Present\t");
117 if (isValidTimestamp(displayPresentTime)) {
118 outString.appendFormat("%" PRId64 "\n", displayPresentTime);
119 } else if (!addPostCompositeCalled || displayPresentFence->isValid()) {
120 outString.appendFormat("Pending\n");
121 } else {
122 outString.appendFormat("N/A\n");
123 }
124
125 outString.appendFormat("--- Display Retire\t");
126 if (isValidTimestamp(displayRetireTime)) {
127 outString.appendFormat("%" PRId64 "\n", displayRetireTime);
128 } else if (!addRetireCalled || displayRetireFence->isValid()) {
129 outString.appendFormat("Pending\n");
130 } else {
131 outString.appendFormat("N/A\n");
132 }
133
134 outString.appendFormat("--- Release \t");
135 if (isValidTimestamp(releaseTime)) {
136 outString.appendFormat("%" PRId64 "\n", releaseTime);
137 } else {
138 outString.appendFormat("Pending\n");
139 }
140}
141
142
143// ============================================================================
144// FrameEventHistory
145// ============================================================================
146
147namespace {
148
149struct FrameNumberEqual {
150 FrameNumberEqual(uint64_t frameNumber) : mFrameNumber(frameNumber) {}
151 bool operator()(const FrameEvents& frame) {
152 return frame.valid && mFrameNumber == frame.frameNumber;
153 }
154 const uint64_t mFrameNumber;
155};
156
157} // namespace
158
159
160FrameEvents* FrameEventHistory::getFrame(uint64_t frameNumber) {
161 auto frame = std::find_if(
162 mFrames.begin(), mFrames.end(), FrameNumberEqual(frameNumber));
163 return frame == mFrames.end() ? nullptr : &(*frame);
164}
165
166FrameEvents* FrameEventHistory::getFrame(uint64_t frameNumber, size_t* iHint) {
167 *iHint = std::min(*iHint, mFrames.size());
168 auto hint = mFrames.begin() + *iHint;
169 auto frame = std::find_if(
170 hint, mFrames.end(), FrameNumberEqual(frameNumber));
171 if (frame == mFrames.end()) {
172 frame = std::find_if(
173 mFrames.begin(), hint, FrameNumberEqual(frameNumber));
174 if (frame == hint) {
175 return nullptr;
176 }
177 }
178 *iHint = static_cast<size_t>(std::distance(mFrames.begin(), frame));
179 return &(*frame);
180}
181
182void FrameEventHistory::checkFencesForCompletion() {
183 for (auto& frame : mFrames) {
184 frame.checkFencesForCompletion();
185 }
186}
187
188// Uses !|valid| as the MSB.
189static bool FrameNumberLessThan(
190 const FrameEvents& lhs, const FrameEvents& rhs) {
191 if (lhs.valid == rhs.valid) {
192 return lhs.frameNumber < rhs.frameNumber;
193 }
194 return lhs.valid;
195}
196
197void FrameEventHistory::dump(String8& outString) const {
198 auto earliestFrame = std::min_element(
199 mFrames.begin(), mFrames.end(), &FrameNumberLessThan);
200 if (!earliestFrame->valid) {
201 outString.appendFormat("-- N/A\n");
202 return;
203 }
204 for (auto frame = earliestFrame; frame != mFrames.end(); ++frame) {
205 frame->dump(outString);
206 }
207 for (auto frame = mFrames.begin(); frame != earliestFrame; ++frame) {
208 frame->dump(outString);
209 }
210}
211
212void FrameEventHistory::addQueue(const NewFrameEventsEntry& newFrameEntry) {
213 // Overwrite all fields of the frame with default values unless set here.
214 FrameEvents newTimestamps;
215 newTimestamps.frameNumber = newFrameEntry.frameNumber;
216 newTimestamps.postedTime = newFrameEntry.postedTime;
217 newTimestamps.requestedPresentTime = newFrameEntry.requestedPresentTime;
218 newTimestamps.acquireFence = newFrameEntry.acquireFence;
219 newTimestamps.valid = true;
220 mFrames[mQueueOffset] = newTimestamps;
221
222 mQueueOffset = mQueueOffset + 1;
223 if (mQueueOffset >= mFrames.size()) {
224 mQueueOffset = 0;
225 }
226}
227
228void FrameEventHistory::addLatch(uint64_t frameNumber, nsecs_t latchTime) {
229 FrameEvents* frame = getFrame(frameNumber, &mCompositionOffset);
230 if (frame == nullptr) {
231 ALOGE("FrameEventHistory::addLatch: Did not find frame.");
232 return;
233 }
234 frame->latchTime = latchTime;
235 return;
236}
237
238void FrameEventHistory::addPreComposition(
239 uint64_t frameNumber, nsecs_t refreshStartTime) {
240 FrameEvents* frame = getFrame(frameNumber, &mCompositionOffset);
241 if (frame == nullptr) {
242 ALOGE("FrameEventHistory::addPreComposition: Did not find frame.");
243 return;
244 }
245 frame->lastRefreshStartTime = refreshStartTime;
246 if (!isValidTimestamp(frame->firstRefreshStartTime)) {
247 frame->firstRefreshStartTime = refreshStartTime;
248 }
249}
250
251void FrameEventHistory::addPostComposition(uint64_t frameNumber,
252 sp<Fence> gpuCompositionDone, sp<Fence> displayPresent) {
253 FrameEvents* frame = getFrame(frameNumber, &mCompositionOffset);
254 if (frame == nullptr) {
255 ALOGE("FrameEventHistory::addPostComposition: Did not find frame.");
256 return;
257 }
258
259 // Only get GPU and present info for the first composite.
260 if (!frame->addPostCompositeCalled) {
261 frame->addPostCompositeCalled = true;
262 frame->gpuCompositionDoneFence = gpuCompositionDone;
263 if (!frame->displayPresentFence->isValid()) {
264 frame->displayPresentFence = displayPresent;
265 }
266 }
267}
268
269void FrameEventHistory::addRetire(
270 uint64_t frameNumber, sp<Fence> displayRetire) {
271 FrameEvents* frame = getFrame(frameNumber, &mRetireOffset);
272 if (frame == nullptr) {
273 ALOGE("FrameEventHistory::addRetire: Did not find frame.");
274 return;
275 }
276 frame->addRetireCalled = true;
277 frame->displayRetireFence = displayRetire;
278}
279
280void FrameEventHistory::addRelease(
281 uint64_t frameNumber, sp<Fence> release) {
282 FrameEvents* frame = getFrame(frameNumber, &mReleaseOffset);
283 if (frame == nullptr) {
284 ALOGE("FrameEventHistory::addRelease: Did not find frame.");
285 return;
286 }
287 frame->releaseFence = release;
288}
289
290} // namespace android