1 /*
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 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
18
19 #include <inttypes.h>
20 #include "FenceTracker.h"
21 #include "Layer.h"
22 #include <utils/Trace.h>
23
24 namespace android {
25
FenceTracker()26 FenceTracker::FenceTracker() :
27 mFrameCounter(0),
28 mOffset(0),
29 mFrames() {}
30
dump(String8 * outString)31 void FenceTracker::dump(String8* outString) {
32 Mutex::Autolock lock(mMutex);
33 checkFencesForCompletion();
34
35 for (size_t i = 0; i < MAX_FRAME_HISTORY; i++) {
36 int index = (mOffset + i) % MAX_FRAME_HISTORY;
37 const FrameRecord& frame = mFrames[index];
38
39 outString->appendFormat("Frame %" PRIu64 "\n", frame.frameId);
40 outString->appendFormat("- Refresh start\t%" PRId64 "\n",
41 frame.refreshStartTime);
42
43 if (frame.glesCompositionDoneTime) {
44 outString->appendFormat("- GLES done\t%" PRId64 "\n",
45 frame.glesCompositionDoneTime);
46 } else if (frame.glesCompositionDoneFence != Fence::NO_FENCE) {
47 outString->append("- GLES done\tNot signaled\n");
48 }
49 if (frame.retireTime) {
50 outString->appendFormat("- Retire\t%" PRId64 "\n",
51 frame.retireTime);
52 } else {
53 outString->append("- Retire\tNot signaled\n");
54 }
55 for (const auto& kv : frame.layers) {
56 const LayerRecord& layer = kv.second;
57 outString->appendFormat("-- %s\n", layer.name.string());
58 outString->appendFormat("---- Frame # %" PRIu64 " (%s)\n",
59 layer.frameNumber,
60 layer.isGlesComposition ? "GLES" : "HWC");
61 outString->appendFormat("---- Posted\t%" PRId64 "\n",
62 layer.postedTime);
63 if (layer.acquireTime) {
64 outString->appendFormat("---- Acquire\t%" PRId64 "\n",
65 layer.acquireTime);
66 } else {
67 outString->append("---- Acquire\tNot signaled\n");
68 }
69 if (layer.releaseTime) {
70 outString->appendFormat("---- Release\t%" PRId64 "\n",
71 layer.releaseTime);
72 } else {
73 outString->append("---- Release\tNot signaled\n");
74 }
75 }
76 }
77 }
78
isValidTimestamp(nsecs_t time)79 static inline bool isValidTimestamp(nsecs_t time) {
80 return time > 0 && time < INT64_MAX;
81 }
82
checkFencesForCompletion()83 void FenceTracker::checkFencesForCompletion() {
84 ATRACE_CALL();
85 for (auto& frame : mFrames) {
86 if (frame.retireFence != Fence::NO_FENCE) {
87 nsecs_t time = frame.retireFence->getSignalTime();
88 if (isValidTimestamp(time)) {
89 frame.retireTime = time;
90 frame.retireFence = Fence::NO_FENCE;
91 }
92 }
93 if (frame.glesCompositionDoneFence != Fence::NO_FENCE) {
94 nsecs_t time = frame.glesCompositionDoneFence->getSignalTime();
95 if (isValidTimestamp(time)) {
96 frame.glesCompositionDoneTime = time;
97 frame.glesCompositionDoneFence = Fence::NO_FENCE;
98 }
99 }
100 for (auto& kv : frame.layers) {
101 LayerRecord& layer = kv.second;
102 if (layer.acquireFence != Fence::NO_FENCE) {
103 nsecs_t time = layer.acquireFence->getSignalTime();
104 if (isValidTimestamp(time)) {
105 layer.acquireTime = time;
106 layer.acquireFence = Fence::NO_FENCE;
107 }
108 }
109 if (layer.releaseFence != Fence::NO_FENCE) {
110 nsecs_t time = layer.releaseFence->getSignalTime();
111 if (isValidTimestamp(time)) {
112 layer.releaseTime = time;
113 layer.releaseFence = Fence::NO_FENCE;
114 }
115 }
116 }
117 }
118 }
119
addFrame(nsecs_t refreshStartTime,sp<Fence> retireFence,const Vector<sp<Layer>> & layers,sp<Fence> glDoneFence)120 void FenceTracker::addFrame(nsecs_t refreshStartTime, sp<Fence> retireFence,
121 const Vector<sp<Layer>>& layers, sp<Fence> glDoneFence) {
122 ATRACE_CALL();
123 Mutex::Autolock lock(mMutex);
124 FrameRecord& frame = mFrames[mOffset];
125 FrameRecord& prevFrame = mFrames[(mOffset + MAX_FRAME_HISTORY - 1) %
126 MAX_FRAME_HISTORY];
127 frame.layers.clear();
128
129 bool wasGlesCompositionDone = false;
130 const size_t count = layers.size();
131 for (size_t i = 0; i < count; i++) {
132 String8 name;
133 uint64_t frameNumber;
134 bool glesComposition;
135 nsecs_t postedTime;
136 sp<Fence> acquireFence;
137 sp<Fence> prevReleaseFence;
138 int32_t key = layers[i]->getSequence();
139
140 layers[i]->getFenceData(&name, &frameNumber, &glesComposition,
141 &postedTime, &acquireFence, &prevReleaseFence);
142 #ifdef USE_HWC2
143 if (glesComposition) {
144 frame.layers.emplace(std::piecewise_construct,
145 std::forward_as_tuple(key),
146 std::forward_as_tuple(name, frameNumber, glesComposition,
147 postedTime, 0, 0, acquireFence, prevReleaseFence));
148 wasGlesCompositionDone = true;
149 } else {
150 frame.layers.emplace(std::piecewise_construct,
151 std::forward_as_tuple(key),
152 std::forward_as_tuple(name, frameNumber, glesComposition,
153 postedTime, 0, 0, acquireFence, Fence::NO_FENCE));
154
155 auto prevLayer = prevFrame.layers.find(key);
156 if (prevLayer != prevFrame.layers.end()) {
157 prevLayer->second.releaseFence = prevReleaseFence;
158 }
159 }
160 #else
161 frame.layers.emplace(std::piecewise_construct,
162 std::forward_as_tuple(key),
163 std::forward_as_tuple(name, frameNumber, glesComposition,
164 postedTime, 0, 0, acquireFence,
165 glesComposition ? Fence::NO_FENCE : prevReleaseFence));
166 if (glesComposition) {
167 wasGlesCompositionDone = true;
168 }
169 #endif
170 frame.layers.emplace(std::piecewise_construct,
171 std::forward_as_tuple(key),
172 std::forward_as_tuple(name, frameNumber, glesComposition,
173 postedTime, 0, 0, acquireFence, prevReleaseFence));
174 }
175
176 frame.frameId = mFrameCounter;
177 frame.refreshStartTime = refreshStartTime;
178 frame.retireTime = 0;
179 frame.glesCompositionDoneTime = 0;
180 prevFrame.retireFence = retireFence;
181 frame.retireFence = Fence::NO_FENCE;
182 frame.glesCompositionDoneFence = wasGlesCompositionDone ? glDoneFence :
183 Fence::NO_FENCE;
184
185 mOffset = (mOffset + 1) % MAX_FRAME_HISTORY;
186 mFrameCounter++;
187
188 checkFencesForCompletion();
189 }
190
191 } // namespace android
192