Home | History | Annotate | Download | only in surfaceflinger
      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