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 
     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