123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252 |
- /*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- // This is needed for stdint.h to define INT64_MAX in C++
- #define __STDC_LIMIT_MACROS
- #include <inttypes.h>
- #include <cutils/log.h>
- #include <ui/Fence.h>
- #include <ui/FrameStats.h>
- #include <utils/String8.h>
- #include "FrameTracker.h"
- #include "EventLog/EventLog.h"
- namespace android {
- FrameTracker::FrameTracker() :
- mOffset(0),
- mNumFences(0),
- mDisplayPeriod(0) {
- resetFrameCountersLocked();
- }
- void FrameTracker::setDesiredPresentTime(nsecs_t presentTime) {
- Mutex::Autolock lock(mMutex);
- mFrameRecords[mOffset].desiredPresentTime = presentTime;
- }
- void FrameTracker::setFrameReadyTime(nsecs_t readyTime) {
- Mutex::Autolock lock(mMutex);
- mFrameRecords[mOffset].frameReadyTime = readyTime;
- }
- void FrameTracker::setFrameReadyFence(const sp<Fence>& readyFence) {
- Mutex::Autolock lock(mMutex);
- mFrameRecords[mOffset].frameReadyFence = readyFence;
- mNumFences++;
- }
- void FrameTracker::setActualPresentTime(nsecs_t presentTime) {
- Mutex::Autolock lock(mMutex);
- mFrameRecords[mOffset].actualPresentTime = presentTime;
- }
- void FrameTracker::setActualPresentFence(const sp<Fence>& readyFence) {
- Mutex::Autolock lock(mMutex);
- mFrameRecords[mOffset].actualPresentFence = readyFence;
- mNumFences++;
- }
- void FrameTracker::setDisplayRefreshPeriod(nsecs_t displayPeriod) {
- Mutex::Autolock lock(mMutex);
- mDisplayPeriod = displayPeriod;
- }
- void FrameTracker::advanceFrame() {
- Mutex::Autolock lock(mMutex);
- // Update the statistic to include the frame we just finished.
- updateStatsLocked(mOffset);
- // Advance to the next frame.
- mOffset = (mOffset+1) % NUM_FRAME_RECORDS;
- mFrameRecords[mOffset].desiredPresentTime = INT64_MAX;
- mFrameRecords[mOffset].frameReadyTime = INT64_MAX;
- mFrameRecords[mOffset].actualPresentTime = INT64_MAX;
- if (mFrameRecords[mOffset].frameReadyFence != NULL) {
- // We're clobbering an unsignaled fence, so we need to decrement the
- // fence count.
- mFrameRecords[mOffset].frameReadyFence = NULL;
- mNumFences--;
- }
- if (mFrameRecords[mOffset].actualPresentFence != NULL) {
- // We're clobbering an unsignaled fence, so we need to decrement the
- // fence count.
- mFrameRecords[mOffset].actualPresentFence = NULL;
- mNumFences--;
- }
- // Clean up the signaled fences to keep the number of open fence FDs in
- // this process reasonable.
- processFencesLocked();
- }
- void FrameTracker::clearStats() {
- Mutex::Autolock lock(mMutex);
- for (size_t i = 0; i < NUM_FRAME_RECORDS; i++) {
- mFrameRecords[i].desiredPresentTime = 0;
- mFrameRecords[i].frameReadyTime = 0;
- mFrameRecords[i].actualPresentTime = 0;
- mFrameRecords[i].frameReadyFence.clear();
- mFrameRecords[i].actualPresentFence.clear();
- }
- mNumFences = 0;
- mFrameRecords[mOffset].desiredPresentTime = INT64_MAX;
- mFrameRecords[mOffset].frameReadyTime = INT64_MAX;
- mFrameRecords[mOffset].actualPresentTime = INT64_MAX;
- }
- void FrameTracker::getStats(FrameStats* outStats) const {
- Mutex::Autolock lock(mMutex);
- processFencesLocked();
- outStats->refreshPeriodNano = mDisplayPeriod;
- const size_t offset = mOffset;
- for (size_t i = 1; i < NUM_FRAME_RECORDS; i++) {
- const size_t index = (offset + i) % NUM_FRAME_RECORDS;
- // Skip frame records with no data (if buffer not yet full).
- if (mFrameRecords[index].desiredPresentTime == 0) {
- continue;
- }
- nsecs_t desiredPresentTimeNano = mFrameRecords[index].desiredPresentTime;
- outStats->desiredPresentTimesNano.push_back(desiredPresentTimeNano);
- nsecs_t actualPresentTimeNano = mFrameRecords[index].actualPresentTime;
- outStats->actualPresentTimesNano.push_back(actualPresentTimeNano);
- nsecs_t frameReadyTimeNano = mFrameRecords[index].frameReadyTime;
- outStats->frameReadyTimesNano.push_back(frameReadyTimeNano);
- }
- }
- void FrameTracker::logAndResetStats(const String8& name) {
- Mutex::Autolock lock(mMutex);
- logStatsLocked(name);
- resetFrameCountersLocked();
- }
- void FrameTracker::processFencesLocked() const {
- FrameRecord* records = const_cast<FrameRecord*>(mFrameRecords);
- int& numFences = const_cast<int&>(mNumFences);
- for (int i = 1; i < NUM_FRAME_RECORDS && numFences > 0; i++) {
- size_t idx = (mOffset+NUM_FRAME_RECORDS-i) % NUM_FRAME_RECORDS;
- bool updated = false;
- const sp<Fence>& rfence = records[idx].frameReadyFence;
- if (rfence != NULL) {
- records[idx].frameReadyTime = rfence->getSignalTime();
- if (records[idx].frameReadyTime < INT64_MAX) {
- records[idx].frameReadyFence = NULL;
- numFences--;
- updated = true;
- }
- }
- const sp<Fence>& pfence = records[idx].actualPresentFence;
- if (pfence != NULL) {
- records[idx].actualPresentTime = pfence->getSignalTime();
- if (records[idx].actualPresentTime < INT64_MAX) {
- records[idx].actualPresentFence = NULL;
- numFences--;
- updated = true;
- }
- }
- if (updated) {
- updateStatsLocked(idx);
- }
- }
- }
- void FrameTracker::updateStatsLocked(size_t newFrameIdx) const {
- int* numFrames = const_cast<int*>(mNumFrames);
- if (mDisplayPeriod > 0 && isFrameValidLocked(newFrameIdx)) {
- size_t prevFrameIdx = (newFrameIdx+NUM_FRAME_RECORDS-1) %
- NUM_FRAME_RECORDS;
- if (isFrameValidLocked(prevFrameIdx)) {
- nsecs_t newPresentTime =
- mFrameRecords[newFrameIdx].actualPresentTime;
- nsecs_t prevPresentTime =
- mFrameRecords[prevFrameIdx].actualPresentTime;
- nsecs_t duration = newPresentTime - prevPresentTime;
- int numPeriods = int((duration + mDisplayPeriod/2) /
- mDisplayPeriod);
- for (int i = 0; i < NUM_FRAME_BUCKETS-1; i++) {
- int nextBucket = 1 << (i+1);
- if (numPeriods < nextBucket) {
- numFrames[i]++;
- return;
- }
- }
- // The last duration bucket is a catch-all.
- numFrames[NUM_FRAME_BUCKETS-1]++;
- }
- }
- }
- void FrameTracker::resetFrameCountersLocked() {
- for (int i = 0; i < NUM_FRAME_BUCKETS; i++) {
- mNumFrames[i] = 0;
- }
- }
- void FrameTracker::logStatsLocked(const String8& name) const {
- for (int i = 0; i < NUM_FRAME_BUCKETS; i++) {
- if (mNumFrames[i] > 0) {
- EventLog::logFrameDurations(name, mNumFrames, NUM_FRAME_BUCKETS);
- return;
- }
- }
- }
- bool FrameTracker::isFrameValidLocked(size_t idx) const {
- return mFrameRecords[idx].actualPresentTime > 0 &&
- mFrameRecords[idx].actualPresentTime < INT64_MAX;
- }
- void FrameTracker::dumpStats(String8& result) const {
- Mutex::Autolock lock(mMutex);
- processFencesLocked();
- const size_t o = mOffset;
- for (size_t i = 1; i < NUM_FRAME_RECORDS; i++) {
- const size_t index = (o+i) % NUM_FRAME_RECORDS;
- result.appendFormat("%" PRId64 "\t%" PRId64 "\t%" PRId64 "\n",
- mFrameRecords[index].desiredPresentTime,
- mFrameRecords[index].actualPresentTime,
- mFrameRecords[index].frameReadyTime);
- }
- result.append("\n");
- }
- } // namespace android
|