FrameTracker.cpp revision 4b0eba949cc026ffb2c75313042d8a7bcb3fcf86
1/*
2 * Copyright (C) 2012 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// This is needed for stdint.h to define INT64_MAX in C++
18#define __STDC_LIMIT_MACROS
19
20#include <ui/Fence.h>
21
22#include <utils/String8.h>
23
24#include "FrameTracker.h"
25
26namespace android {
27
28FrameTracker::FrameTracker() :
29        mOffset(0),
30        mNumFences(0) {
31}
32
33void FrameTracker::setDesiredPresentTime(nsecs_t presentTime) {
34    Mutex::Autolock lock(mMutex);
35    mFrameRecords[mOffset].desiredPresentTime = presentTime;
36}
37
38void FrameTracker::setFrameReadyTime(nsecs_t readyTime) {
39    Mutex::Autolock lock(mMutex);
40    mFrameRecords[mOffset].frameReadyTime = readyTime;
41}
42
43void FrameTracker::setFrameReadyFence(const sp<Fence>& readyFence) {
44    Mutex::Autolock lock(mMutex);
45    mFrameRecords[mOffset].frameReadyFence = readyFence;
46    mNumFences++;
47}
48
49void FrameTracker::setActualPresentTime(nsecs_t presentTime) {
50    Mutex::Autolock lock(mMutex);
51    mFrameRecords[mOffset].actualPresentTime = presentTime;
52}
53
54void FrameTracker::setActualPresentFence(const sp<Fence>& readyFence) {
55    Mutex::Autolock lock(mMutex);
56    mFrameRecords[mOffset].actualPresentFence = readyFence;
57    mNumFences++;
58}
59
60void FrameTracker::advanceFrame() {
61    Mutex::Autolock lock(mMutex);
62    mOffset = (mOffset+1) % NUM_FRAME_RECORDS;
63    mFrameRecords[mOffset].desiredPresentTime = INT64_MAX;
64    mFrameRecords[mOffset].frameReadyTime = INT64_MAX;
65    mFrameRecords[mOffset].actualPresentTime = INT64_MAX;
66
67    if (mFrameRecords[mOffset].frameReadyFence != NULL) {
68        // We're clobbering an unsignaled fence, so we need to decrement the
69        // fence count.
70        mFrameRecords[mOffset].frameReadyFence = NULL;
71        mNumFences--;
72    }
73
74    if (mFrameRecords[mOffset].actualPresentFence != NULL) {
75        // We're clobbering an unsignaled fence, so we need to decrement the
76        // fence count.
77        mFrameRecords[mOffset].actualPresentFence = NULL;
78        mNumFences--;
79    }
80
81    // Clean up the signaled fences to keep the number of open fence FDs in
82    // this process reasonable.
83    processFencesLocked();
84}
85
86void FrameTracker::clear() {
87    Mutex::Autolock lock(mMutex);
88    for (size_t i = 0; i < NUM_FRAME_RECORDS; i++) {
89        mFrameRecords[i].desiredPresentTime = 0;
90        mFrameRecords[i].frameReadyTime = 0;
91        mFrameRecords[i].actualPresentTime = 0;
92        mFrameRecords[i].frameReadyFence.clear();
93        mFrameRecords[i].actualPresentFence.clear();
94    }
95    mNumFences = 0;
96    mFrameRecords[mOffset].desiredPresentTime = INT64_MAX;
97    mFrameRecords[mOffset].frameReadyTime = INT64_MAX;
98    mFrameRecords[mOffset].actualPresentTime = INT64_MAX;
99}
100
101void FrameTracker::processFencesLocked() const {
102    FrameRecord* records = const_cast<FrameRecord*>(mFrameRecords);
103    int& numFences = const_cast<int&>(mNumFences);
104
105    for (int i = 1; i < NUM_FRAME_RECORDS && numFences > 0; i++) {
106        size_t idx = (mOffset+NUM_FRAME_RECORDS-i) % NUM_FRAME_RECORDS;
107
108        const sp<Fence>& rfence = records[idx].frameReadyFence;
109        if (rfence != NULL) {
110            records[idx].frameReadyTime = rfence->getSignalTime();
111            if (records[idx].frameReadyTime < INT64_MAX) {
112                records[idx].frameReadyFence = NULL;
113                numFences--;
114            }
115        }
116
117        const sp<Fence>& pfence = records[idx].actualPresentFence;
118        if (pfence != NULL) {
119            records[idx].actualPresentTime = pfence->getSignalTime();
120            if (records[idx].actualPresentTime < INT64_MAX) {
121                records[idx].actualPresentFence = NULL;
122                numFences--;
123            }
124        }
125    }
126}
127
128void FrameTracker::dump(String8& result) const {
129    Mutex::Autolock lock(mMutex);
130    processFencesLocked();
131
132    const size_t o = mOffset;
133    for (size_t i = 1; i < NUM_FRAME_RECORDS; i++) {
134        const size_t index = (o+i) % NUM_FRAME_RECORDS;
135        result.appendFormat("%lld\t%lld\t%lld\n",
136            mFrameRecords[index].desiredPresentTime,
137            mFrameRecords[index].actualPresentTime,
138            mFrameRecords[index].frameReadyTime);
139    }
140    result.append("\n");
141}
142
143} // namespace android
144