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 26 FenceTracker::FenceTracker() : 27 mFrameCounter(0), 28 mOffset(0), 29 mFrames(), 30 mMutex() { 31 } 32 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 81 static inline bool isValidTimestamp(nsecs_t time) { 82 return time > 0 && time < INT64_MAX; 83 } 84 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 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 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