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 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 79 static inline bool isValidTimestamp(nsecs_t time) { 80 return time > 0 && time < INT64_MAX; 81 } 82 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 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