/* * 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. */ #ifndef ANDROID_FRAMETRACKER_H #define ANDROID_FRAMETRACKER_H #include #include #include #include #include namespace android { class String8; // FrameTracker tracks information about the most recently rendered frames. It // uses a circular buffer of frame records, and is *NOT* thread-safe - // mutexing must be done at a higher level if multi-threaded access is // possible. // // Some of the time values tracked may be set either as a specific timestamp // or a fence. When a non-NULL fence is set for a given time value, the // signal time of that fence is used instead of the timestamp. class FrameTracker { public: // NUM_FRAME_RECORDS is the size of the circular buffer used to track the // frame time history. enum { NUM_FRAME_RECORDS = 128 }; enum { NUM_FRAME_BUCKETS = 7 }; FrameTracker(); // setDesiredPresentTime sets the time at which the current frame // should be presented to the user under ideal (i.e. zero latency) // conditions. void setDesiredPresentTime(nsecs_t desiredPresentTime); // setFrameReadyTime sets the time at which the current frame became ready // to be presented to the user. For example, if the frame contents is // being written to memory by some asynchronous hardware, this would be // the time at which those writes completed. void setFrameReadyTime(nsecs_t readyTime); // setFrameReadyFence sets the fence that is used to get the time at which // the current frame became ready to be presented to the user. void setFrameReadyFence(std::shared_ptr&& readyFence); // setActualPresentTime sets the timestamp at which the current frame became // visible to the user. void setActualPresentTime(nsecs_t displayTime); // setActualPresentFence sets the fence that is used to get the time // at which the current frame became visible to the user. void setActualPresentFence(std::shared_ptr&& fence); // setDisplayRefreshPeriod sets the display refresh period in nanoseconds. // This is used to compute frame presentation duration statistics relative // to this period. void setDisplayRefreshPeriod(nsecs_t displayPeriod); // advanceFrame advances the frame tracker to the next frame. void advanceFrame(); // clearStats clears the tracked frame stats. void clearStats(); // getStats gets the tracked frame stats. void getStats(FrameStats* outStats) const; // logAndResetStats dumps the current statistics to the binary event log // and then resets the accumulated statistics to their initial values. void logAndResetStats(const String8& name); // dumpStats dump appends the current frame display time history to the result string. void dumpStats(String8& result) const; private: struct FrameRecord { FrameRecord() : desiredPresentTime(0), frameReadyTime(0), actualPresentTime(0) {} nsecs_t desiredPresentTime; nsecs_t frameReadyTime; nsecs_t actualPresentTime; std::shared_ptr frameReadyFence; std::shared_ptr actualPresentFence; }; // processFences iterates over all the frame records that have a fence set // and replaces that fence with a timestamp if the fence has signaled. If // the fence is not signaled the record's displayTime is set to INT64_MAX. // // This method is const because although it modifies the frame records it // does so in such a way that the information represented should not // change. This allows it to be called from the dump method. void processFencesLocked() const; // updateStatsLocked updates the running statistics that are gathered // about the frame times. void updateStatsLocked(size_t newFrameIdx) const; // resetFrameCounteresLocked sets all elements of the mNumFrames array to // 0. void resetFrameCountersLocked(); // logStatsLocked dumps the current statistics to the binary event log. void logStatsLocked(const String8& name) const; // isFrameValidLocked returns true if the data for the given frame index is // valid and has all arrived (i.e. there are no oustanding fences). bool isFrameValidLocked(size_t idx) const; // mFrameRecords is the circular buffer storing the tracked data for each // frame. FrameRecord mFrameRecords[NUM_FRAME_RECORDS]; // mOffset is the offset into mFrameRecords of the current frame. size_t mOffset; // mNumFences is the total number of fences set in the frame records. It // is incremented each time a fence is added and decremented each time a // signaled fence is removed in processFences or if advanceFrame clobbers // a fence. // // The number of fences is tracked so that the run time of processFences // doesn't grow with NUM_FRAME_RECORDS. int mNumFences; // mNumFrames keeps a count of the number of frames with a duration in a // particular range of vsync periods. Element n of the array stores the // number of frames with duration in the half-inclusive range // [2^n, 2^(n+1)). The last element of the array contains the count for // all frames with duration greater than 2^(NUM_FRAME_BUCKETS-1). int32_t mNumFrames[NUM_FRAME_BUCKETS]; // mDisplayPeriod is the display refresh period of the display for which // this FrameTracker is gathering information. nsecs_t mDisplayPeriod; // mMutex is used to protect access to all member variables. mutable Mutex mMutex; }; } #endif // ANDROID_FRAMETRACKER_H