blob: 3ff9bbfad68d70668f66f4f2f66f01a6df3b7a95 [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 }
51 if (frame.retireTime) {
52 outString->appendFormat("- Retire\t%" PRId64 "\n",
53 frame.retireTime);
54 } else {
55 outString->append("- Retire\tNot signaled\n");
56 }
57 for (const auto& kv : frame.layers) {
58 const LayerRecord& layer = kv.second;
59 outString->appendFormat("-- %s\n", layer.name.string());
60 outString->appendFormat("---- Frame # %" PRIu64 " (%s)\n",
61 layer.frameNumber,
62 layer.isGlesComposition ? "GLES" : "HWC");
63 outString->appendFormat("---- Posted\t%" PRId64 "\n",
64 layer.postedTime);
65 if (layer.acquireTime) {
66 outString->appendFormat("---- Acquire\t%" PRId64 "\n",
67 layer.acquireTime);
68 } else {
69 outString->append("---- Acquire\tNot signaled\n");
70 }
71 if (layer.releaseTime) {
72 outString->appendFormat("---- Release\t%" PRId64 "\n",
73 layer.releaseTime);
74 } else {
75 outString->append("---- Release\tNot signaled\n");
76 }
77 }
78 }
79}
80
81static inline bool isValidTimestamp(nsecs_t time) {
82 return time > 0 && time < INT64_MAX;
83}
84
85void FenceTracker::checkFencesForCompletion() {
Pablo Ceballos69a1a382016-03-30 15:28:05 -070086 ATRACE_CALL();
Pablo Ceballos40845df2016-01-25 17:41:15 -080087 for (auto& frame : mFrames) {
88 if (frame.retireFence != Fence::NO_FENCE) {
89 nsecs_t time = frame.retireFence->getSignalTime();
90 if (isValidTimestamp(time)) {
91 frame.retireTime = time;
92 frame.retireFence = Fence::NO_FENCE;
93 }
94 }
95 if (frame.glesCompositionDoneFence != Fence::NO_FENCE) {
96 nsecs_t time = frame.glesCompositionDoneFence->getSignalTime();
97 if (isValidTimestamp(time)) {
98 frame.glesCompositionDoneTime = time;
99 frame.glesCompositionDoneFence = Fence::NO_FENCE;
100 }
101 }
102 for (auto& kv : frame.layers) {
103 LayerRecord& layer = kv.second;
104 if (layer.acquireFence != Fence::NO_FENCE) {
105 nsecs_t time = layer.acquireFence->getSignalTime();
106 if (isValidTimestamp(time)) {
107 layer.acquireTime = time;
108 layer.acquireFence = Fence::NO_FENCE;
109 }
110 }
111 if (layer.releaseFence != Fence::NO_FENCE) {
112 nsecs_t time = layer.releaseFence->getSignalTime();
113 if (isValidTimestamp(time)) {
114 layer.releaseTime = time;
115 layer.releaseFence = Fence::NO_FENCE;
116 }
117 }
118 }
119 }
120}
121
122void FenceTracker::addFrame(nsecs_t refreshStartTime, sp<Fence> retireFence,
123 const Vector<sp<Layer>>& layers, sp<Fence> glDoneFence) {
Pablo Ceballos69a1a382016-03-30 15:28:05 -0700124 ATRACE_CALL();
Pablo Ceballos40845df2016-01-25 17:41:15 -0800125 Mutex::Autolock lock(mMutex);
126 FrameRecord& frame = mFrames[mOffset];
127 FrameRecord& prevFrame = mFrames[(mOffset + MAX_FRAME_HISTORY - 1) %
128 MAX_FRAME_HISTORY];
129 frame.layers.clear();
130
131 bool wasGlesCompositionDone = false;
132 const size_t count = layers.size();
133 for (size_t i = 0; i < count; i++) {
134 String8 name;
135 uint64_t frameNumber;
136 bool glesComposition;
137 nsecs_t postedTime;
138 sp<Fence> acquireFence;
139 sp<Fence> prevReleaseFence;
Pablo Ceballosce796e72016-02-04 19:10:51 -0800140 int32_t layerId = layers[i]->getSequence();
Pablo Ceballos40845df2016-01-25 17:41:15 -0800141
142 layers[i]->getFenceData(&name, &frameNumber, &glesComposition,
143 &postedTime, &acquireFence, &prevReleaseFence);
144#ifdef USE_HWC2
145 if (glesComposition) {
146 frame.layers.emplace(std::piecewise_construct,
147 std::forward_as_tuple(key),
148 std::forward_as_tuple(name, frameNumber, glesComposition,
Pablo Ceballosce796e72016-02-04 19:10:51 -0800149 postedTime, FrameTimestamps::INVALID_TIME,
150 FrameTimestamps::INVALID_TIME, acquireFence,
151 prevReleaseFence));
Pablo Ceballos40845df2016-01-25 17:41:15 -0800152 wasGlesCompositionDone = true;
153 } else {
154 frame.layers.emplace(std::piecewise_construct,
155 std::forward_as_tuple(key),
156 std::forward_as_tuple(name, frameNumber, glesComposition,
Pablo Ceballosce796e72016-02-04 19:10:51 -0800157 postedTime, FrameTimestamps::INVALID_TIME,
158 FrameTimestamps::INVALID_TIME, acquireFence,
159 Fence::NO_FENCE));
Pablo Ceballos40845df2016-01-25 17:41:15 -0800160
161 auto prevLayer = prevFrame.layers.find(key);
162 if (prevLayer != prevFrame.layers.end()) {
163 prevLayer->second.releaseFence = prevReleaseFence;
164 }
165 }
166#else
167 frame.layers.emplace(std::piecewise_construct,
Pablo Ceballosce796e72016-02-04 19:10:51 -0800168 std::forward_as_tuple(layerId),
Pablo Ceballos40845df2016-01-25 17:41:15 -0800169 std::forward_as_tuple(name, frameNumber, glesComposition,
170 postedTime, 0, 0, acquireFence,
171 glesComposition ? Fence::NO_FENCE : prevReleaseFence));
172 if (glesComposition) {
173 wasGlesCompositionDone = true;
174 }
175#endif
176 frame.layers.emplace(std::piecewise_construct,
Pablo Ceballosce796e72016-02-04 19:10:51 -0800177 std::forward_as_tuple(layerId),
Pablo Ceballos40845df2016-01-25 17:41:15 -0800178 std::forward_as_tuple(name, frameNumber, glesComposition,
179 postedTime, 0, 0, acquireFence, prevReleaseFence));
180 }
181
182 frame.frameId = mFrameCounter;
183 frame.refreshStartTime = refreshStartTime;
184 frame.retireTime = 0;
185 frame.glesCompositionDoneTime = 0;
186 prevFrame.retireFence = retireFence;
187 frame.retireFence = Fence::NO_FENCE;
188 frame.glesCompositionDoneFence = wasGlesCompositionDone ? glDoneFence :
189 Fence::NO_FENCE;
190
191 mOffset = (mOffset + 1) % MAX_FRAME_HISTORY;
192 mFrameCounter++;
Pablo Ceballos40845df2016-01-25 17:41:15 -0800193}
194
Pablo Ceballosce796e72016-02-04 19:10:51 -0800195bool FenceTracker::getFrameTimestamps(const Layer& layer,
196 uint64_t frameNumber, FrameTimestamps* outTimestamps) {
197 Mutex::Autolock lock(mMutex);
198 checkFencesForCompletion();
199 int32_t layerId = layer.getSequence();
200
201 size_t i = 0;
202 for (; i < MAX_FRAME_HISTORY; i++) {
203 if (mFrames[i].layers.count(layerId) &&
204 mFrames[i].layers[layerId].frameNumber == frameNumber) {
205 break;
206 }
207 }
208 if (i == MAX_FRAME_HISTORY) {
209 return false;
210 }
211
212 const FrameRecord& frameRecord = mFrames[i];
213 const LayerRecord& layerRecord = mFrames[i].layers[layerId];
214 outTimestamps->frameNumber = frameNumber;
215 outTimestamps->postedTime = layerRecord.postedTime;
216 outTimestamps->acquireTime = layerRecord.acquireTime;
217 outTimestamps->refreshStartTime = frameRecord.refreshStartTime;
218 outTimestamps->glCompositionDoneTime = frameRecord.glesCompositionDoneTime;
219 outTimestamps->displayRetireTime = frameRecord.retireTime;
220 outTimestamps->releaseTime = layerRecord.releaseTime;
221 return true;
222}
223
Pablo Ceballos40845df2016-01-25 17:41:15 -0800224} // namespace android