• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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         mMutex() {
31 }
32 
dump(String8 * outString)33 void 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 
isValidTimestamp(nsecs_t time)81 static inline bool isValidTimestamp(nsecs_t time) {
82     return time > 0 && time < INT64_MAX;
83 }
84 
checkFencesForCompletion()85 void FenceTracker::checkFencesForCompletion() {
86     ATRACE_CALL();
87     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 
addFrame(nsecs_t refreshStartTime,sp<Fence> retireFence,const Vector<sp<Layer>> & layers,sp<Fence> glDoneFence)122 void FenceTracker::addFrame(nsecs_t refreshStartTime, sp<Fence> retireFence,
123         const Vector<sp<Layer>>& layers, sp<Fence> glDoneFence) {
124     ATRACE_CALL();
125     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;
140         int32_t layerId = layers[i]->getSequence();
141 
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(layerId),
148                     std::forward_as_tuple(name, frameNumber, glesComposition,
149                     postedTime, 0, 0, acquireFence, prevReleaseFence));
150             wasGlesCompositionDone = true;
151         } else {
152             frame.layers.emplace(std::piecewise_construct,
153                     std::forward_as_tuple(layerId),
154                     std::forward_as_tuple(name, frameNumber, glesComposition,
155                     postedTime, 0, 0, acquireFence, Fence::NO_FENCE));
156             auto prevLayer = prevFrame.layers.find(layerId);
157             if (prevLayer != prevFrame.layers.end()) {
158                 prevLayer->second.releaseFence = prevReleaseFence;
159             }
160         }
161 #else
162         frame.layers.emplace(std::piecewise_construct,
163                 std::forward_as_tuple(layerId),
164                 std::forward_as_tuple(name, frameNumber, glesComposition,
165                 postedTime, 0, 0, acquireFence,
166                 glesComposition ? Fence::NO_FENCE : prevReleaseFence));
167         if (glesComposition) {
168             wasGlesCompositionDone = true;
169         }
170 #endif
171         frame.layers.emplace(std::piecewise_construct,
172                 std::forward_as_tuple(layerId),
173                 std::forward_as_tuple(name, frameNumber, glesComposition,
174                 postedTime, 0, 0, acquireFence, prevReleaseFence));
175     }
176 
177     frame.frameId = mFrameCounter;
178     frame.refreshStartTime = refreshStartTime;
179     frame.retireTime = 0;
180     frame.glesCompositionDoneTime = 0;
181     prevFrame.retireFence = retireFence;
182     frame.retireFence = Fence::NO_FENCE;
183     frame.glesCompositionDoneFence = wasGlesCompositionDone ? glDoneFence :
184             Fence::NO_FENCE;
185 
186     mOffset = (mOffset + 1) % MAX_FRAME_HISTORY;
187     mFrameCounter++;
188 }
189 
getFrameTimestamps(const Layer & layer,uint64_t frameNumber,FrameTimestamps * outTimestamps)190 bool FenceTracker::getFrameTimestamps(const Layer& layer,
191         uint64_t frameNumber, FrameTimestamps* outTimestamps) {
192     Mutex::Autolock lock(mMutex);
193     checkFencesForCompletion();
194     int32_t layerId = layer.getSequence();
195 
196     size_t i = 0;
197     for (; i < MAX_FRAME_HISTORY; i++) {
198        if (mFrames[i].layers.count(layerId) &&
199                mFrames[i].layers[layerId].frameNumber == frameNumber) {
200            break;
201        }
202     }
203     if (i == MAX_FRAME_HISTORY) {
204         return false;
205     }
206 
207     const FrameRecord& frameRecord = mFrames[i];
208     const LayerRecord& layerRecord = mFrames[i].layers[layerId];
209     outTimestamps->frameNumber = frameNumber;
210     outTimestamps->postedTime = layerRecord.postedTime;
211     outTimestamps->acquireTime = layerRecord.acquireTime;
212     outTimestamps->refreshStartTime = frameRecord.refreshStartTime;
213     outTimestamps->glCompositionDoneTime = frameRecord.glesCompositionDoneTime;
214     outTimestamps->displayRetireTime = frameRecord.retireTime;
215     outTimestamps->releaseTime = layerRecord.releaseTime;
216     return true;
217 }
218 
219 } // namespace android
220