blob: 742c00d9512057d9b33686da22b98cadf361836d [file] [log] [blame]
Pablo Ceballos40845df2016-01-25 17:41:15 -08001/*
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
Pablo Ceballos69a1a382016-03-30 15:28:05 -070017#define ATRACE_TAG ATRACE_TAG_GRAPHICS
18
Pablo Ceballos40845df2016-01-25 17:41:15 -080019#include <inttypes.h>
20#include "FenceTracker.h"
21#include "Layer.h"
Pablo Ceballos69a1a382016-03-30 15:28:05 -070022#include <utils/Trace.h>
Pablo Ceballos40845df2016-01-25 17:41:15 -080023
24namespace android {
25
26FenceTracker::FenceTracker() :
27 mFrameCounter(0),
28 mOffset(0),
Pablo Ceballosce796e72016-02-04 19:10:51 -080029 mFrames(),
30 mMutex() {
31}
Pablo Ceballos40845df2016-01-25 17:41:15 -080032
33void FenceTracker::dump(String8* outString) {
34 Mutex::Autolock lock(mMutex);
35 checkFencesForCompletion();
36
37 for (size_t i = 0; i < MAX_FRAME_HISTORY; i++) {
38 int index = (mOffset + i) % MAX_FRAME_HISTORY;
39 const FrameRecord& frame = mFrames[index];
40
41 outString->appendFormat("Frame %" PRIu64 "\n", frame.frameId);
42 outString->appendFormat("- Refresh start\t%" PRId64 "\n",
43 frame.refreshStartTime);
44
45 if (frame.glesCompositionDoneTime) {
46 outString->appendFormat("- GLES done\t%" PRId64 "\n",
47 frame.glesCompositionDoneTime);
48 } else if (frame.glesCompositionDoneFence != Fence::NO_FENCE) {
49 outString->append("- GLES done\tNot signaled\n");
50 }
Brian Anderson069b3652016-07-22 10:32:47 -070051
52 if (frame.presentTime) {
53 outString->appendFormat("- Present\t%" PRId64 "\n",
54 frame.presentTime);
55 } else if (frame.presentFence != Fence::NO_FENCE) {
56 outString->append("- Present\tNot signaled\n");
57 }
58
Pablo Ceballos40845df2016-01-25 17:41:15 -080059 if (frame.retireTime) {
60 outString->appendFormat("- Retire\t%" PRId64 "\n",
61 frame.retireTime);
Brian Anderson069b3652016-07-22 10:32:47 -070062 } else if (frame.retireFence != Fence::NO_FENCE) {
Pablo Ceballos40845df2016-01-25 17:41:15 -080063 outString->append("- Retire\tNot signaled\n");
64 }
Brian Anderson069b3652016-07-22 10:32:47 -070065
Pablo Ceballos40845df2016-01-25 17:41:15 -080066 for (const auto& kv : frame.layers) {
67 const LayerRecord& layer = kv.second;
68 outString->appendFormat("-- %s\n", layer.name.string());
69 outString->appendFormat("---- Frame # %" PRIu64 " (%s)\n",
70 layer.frameNumber,
71 layer.isGlesComposition ? "GLES" : "HWC");
Brian Andersondbd0ea82016-07-22 09:38:59 -070072 outString->appendFormat("---- Req.Present.\t%" PRId64 "\n",
73 layer.requestedPresentTime);
Pablo Ceballos40845df2016-01-25 17:41:15 -080074 if (layer.acquireTime) {
75 outString->appendFormat("---- Acquire\t%" PRId64 "\n",
76 layer.acquireTime);
77 } else {
78 outString->append("---- Acquire\tNot signaled\n");
79 }
80 if (layer.releaseTime) {
81 outString->appendFormat("---- Release\t%" PRId64 "\n",
82 layer.releaseTime);
83 } else {
84 outString->append("---- Release\tNot signaled\n");
85 }
86 }
87 }
88}
89
90static inline bool isValidTimestamp(nsecs_t time) {
91 return time > 0 && time < INT64_MAX;
92}
93
94void FenceTracker::checkFencesForCompletion() {
Pablo Ceballos69a1a382016-03-30 15:28:05 -070095 ATRACE_CALL();
Pablo Ceballos40845df2016-01-25 17:41:15 -080096 for (auto& frame : mFrames) {
Brian Anderson069b3652016-07-22 10:32:47 -070097 if (frame.presentFence != Fence::NO_FENCE) {
98 nsecs_t time = frame.presentFence->getSignalTime();
99 if (isValidTimestamp(time)) {
100 frame.presentTime = time;
101 frame.presentFence = Fence::NO_FENCE;
102 }
103 }
Pablo Ceballos40845df2016-01-25 17:41:15 -0800104 if (frame.retireFence != Fence::NO_FENCE) {
105 nsecs_t time = frame.retireFence->getSignalTime();
106 if (isValidTimestamp(time)) {
107 frame.retireTime = time;
108 frame.retireFence = Fence::NO_FENCE;
109 }
110 }
111 if (frame.glesCompositionDoneFence != Fence::NO_FENCE) {
112 nsecs_t time = frame.glesCompositionDoneFence->getSignalTime();
113 if (isValidTimestamp(time)) {
114 frame.glesCompositionDoneTime = time;
115 frame.glesCompositionDoneFence = Fence::NO_FENCE;
116 }
117 }
118 for (auto& kv : frame.layers) {
119 LayerRecord& layer = kv.second;
120 if (layer.acquireFence != Fence::NO_FENCE) {
121 nsecs_t time = layer.acquireFence->getSignalTime();
122 if (isValidTimestamp(time)) {
123 layer.acquireTime = time;
124 layer.acquireFence = Fence::NO_FENCE;
125 }
126 }
127 if (layer.releaseFence != Fence::NO_FENCE) {
128 nsecs_t time = layer.releaseFence->getSignalTime();
129 if (isValidTimestamp(time)) {
130 layer.releaseTime = time;
131 layer.releaseFence = Fence::NO_FENCE;
132 }
133 }
134 }
135 }
136}
137
Brian Anderson069b3652016-07-22 10:32:47 -0700138void FenceTracker::addFrame(nsecs_t refreshStartTime, sp<Fence> presentFence,
139 sp<Fence> retireFence, const Vector<sp<Layer>>& layers,
140 sp<Fence> glDoneFence) {
Pablo Ceballos69a1a382016-03-30 15:28:05 -0700141 ATRACE_CALL();
Pablo Ceballos40845df2016-01-25 17:41:15 -0800142 Mutex::Autolock lock(mMutex);
143 FrameRecord& frame = mFrames[mOffset];
144 FrameRecord& prevFrame = mFrames[(mOffset + MAX_FRAME_HISTORY - 1) %
145 MAX_FRAME_HISTORY];
146 frame.layers.clear();
147
148 bool wasGlesCompositionDone = false;
149 const size_t count = layers.size();
150 for (size_t i = 0; i < count; i++) {
151 String8 name;
152 uint64_t frameNumber;
153 bool glesComposition;
Brian Andersondbd0ea82016-07-22 09:38:59 -0700154 nsecs_t requestedPresentTime;
Pablo Ceballos40845df2016-01-25 17:41:15 -0800155 sp<Fence> acquireFence;
156 sp<Fence> prevReleaseFence;
Pablo Ceballosce796e72016-02-04 19:10:51 -0800157 int32_t layerId = layers[i]->getSequence();
Pablo Ceballos40845df2016-01-25 17:41:15 -0800158
159 layers[i]->getFenceData(&name, &frameNumber, &glesComposition,
Brian Andersondbd0ea82016-07-22 09:38:59 -0700160 &requestedPresentTime, &acquireFence, &prevReleaseFence);
Fabien Sanglard9d96de42016-10-11 00:15:18 +0000161#ifdef USE_HWC2
Pablo Ceballos40845df2016-01-25 17:41:15 -0800162 if (glesComposition) {
163 frame.layers.emplace(std::piecewise_construct,
Pablo Ceballos8fc10c32016-06-13 13:21:41 -0700164 std::forward_as_tuple(layerId),
Pablo Ceballos40845df2016-01-25 17:41:15 -0800165 std::forward_as_tuple(name, frameNumber, glesComposition,
Brian Andersondbd0ea82016-07-22 09:38:59 -0700166 requestedPresentTime, 0, 0, acquireFence,
167 prevReleaseFence));
Pablo Ceballos40845df2016-01-25 17:41:15 -0800168 wasGlesCompositionDone = true;
169 } else {
170 frame.layers.emplace(std::piecewise_construct,
Pablo Ceballos8fc10c32016-06-13 13:21:41 -0700171 std::forward_as_tuple(layerId),
Pablo Ceballos40845df2016-01-25 17:41:15 -0800172 std::forward_as_tuple(name, frameNumber, glesComposition,
Brian Andersondbd0ea82016-07-22 09:38:59 -0700173 requestedPresentTime, 0, 0, acquireFence, Fence::NO_FENCE));
Pablo Ceballos8fc10c32016-06-13 13:21:41 -0700174 auto prevLayer = prevFrame.layers.find(layerId);
Pablo Ceballos40845df2016-01-25 17:41:15 -0800175 if (prevLayer != prevFrame.layers.end()) {
176 prevLayer->second.releaseFence = prevReleaseFence;
177 }
178 }
Fabien Sanglard9d96de42016-10-11 00:15:18 +0000179#else
180 frame.layers.emplace(std::piecewise_construct,
181 std::forward_as_tuple(layerId),
182 std::forward_as_tuple(name, frameNumber, glesComposition,
Brian Andersondbd0ea82016-07-22 09:38:59 -0700183 requestedPresentTime, 0, 0, acquireFence,
Fabien Sanglard9d96de42016-10-11 00:15:18 +0000184 glesComposition ? Fence::NO_FENCE : prevReleaseFence));
185 if (glesComposition) {
186 wasGlesCompositionDone = true;
187 }
188#endif
Pablo Ceballos40845df2016-01-25 17:41:15 -0800189 frame.layers.emplace(std::piecewise_construct,
Pablo Ceballosce796e72016-02-04 19:10:51 -0800190 std::forward_as_tuple(layerId),
Pablo Ceballos40845df2016-01-25 17:41:15 -0800191 std::forward_as_tuple(name, frameNumber, glesComposition,
Brian Andersondbd0ea82016-07-22 09:38:59 -0700192 requestedPresentTime, 0, 0, acquireFence, prevReleaseFence));
Pablo Ceballos40845df2016-01-25 17:41:15 -0800193 }
194
195 frame.frameId = mFrameCounter;
196 frame.refreshStartTime = refreshStartTime;
Brian Anderson069b3652016-07-22 10:32:47 -0700197 frame.presentTime = 0;
Pablo Ceballos40845df2016-01-25 17:41:15 -0800198 frame.retireTime = 0;
199 frame.glesCompositionDoneTime = 0;
Brian Anderson069b3652016-07-22 10:32:47 -0700200 frame.presentFence = presentFence;
Pablo Ceballos40845df2016-01-25 17:41:15 -0800201 prevFrame.retireFence = retireFence;
202 frame.retireFence = Fence::NO_FENCE;
203 frame.glesCompositionDoneFence = wasGlesCompositionDone ? glDoneFence :
204 Fence::NO_FENCE;
205
206 mOffset = (mOffset + 1) % MAX_FRAME_HISTORY;
207 mFrameCounter++;
Pablo Ceballos40845df2016-01-25 17:41:15 -0800208}
209
Pablo Ceballosce796e72016-02-04 19:10:51 -0800210bool FenceTracker::getFrameTimestamps(const Layer& layer,
211 uint64_t frameNumber, FrameTimestamps* outTimestamps) {
212 Mutex::Autolock lock(mMutex);
213 checkFencesForCompletion();
214 int32_t layerId = layer.getSequence();
215
216 size_t i = 0;
217 for (; i < MAX_FRAME_HISTORY; i++) {
218 if (mFrames[i].layers.count(layerId) &&
219 mFrames[i].layers[layerId].frameNumber == frameNumber) {
220 break;
221 }
222 }
223 if (i == MAX_FRAME_HISTORY) {
224 return false;
225 }
226
227 const FrameRecord& frameRecord = mFrames[i];
228 const LayerRecord& layerRecord = mFrames[i].layers[layerId];
229 outTimestamps->frameNumber = frameNumber;
Brian Andersondbd0ea82016-07-22 09:38:59 -0700230 outTimestamps->requestedPresentTime = layerRecord.requestedPresentTime;
Pablo Ceballosce796e72016-02-04 19:10:51 -0800231 outTimestamps->acquireTime = layerRecord.acquireTime;
232 outTimestamps->refreshStartTime = frameRecord.refreshStartTime;
233 outTimestamps->glCompositionDoneTime = frameRecord.glesCompositionDoneTime;
Brian Anderson069b3652016-07-22 10:32:47 -0700234 outTimestamps->displayPresentTime = frameRecord.presentTime;
Pablo Ceballosce796e72016-02-04 19:10:51 -0800235 outTimestamps->displayRetireTime = frameRecord.retireTime;
236 outTimestamps->releaseTime = layerRecord.releaseTime;
237 return true;
238}
239
Pablo Ceballos40845df2016-01-25 17:41:15 -0800240} // namespace android