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