| Jamie Gennis | faf77cc | 2013-07-30 15:10:32 -0700 | [diff] [blame] | 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 | #ifndef ANDROID_DISPSYNC_H | 
|  | 18 | #define ANDROID_DISPSYNC_H | 
|  | 19 |  | 
|  | 20 | #include <stddef.h> | 
|  | 21 |  | 
|  | 22 | #include <utils/Mutex.h> | 
|  | 23 | #include <utils/Timers.h> | 
|  | 24 | #include <utils/RefBase.h> | 
|  | 25 |  | 
|  | 26 | namespace android { | 
|  | 27 |  | 
| Andy McFadden | 5167ec6 | 2014-05-22 13:08:43 -0700 | [diff] [blame] | 28 | // Ignore present (retire) fences if the device doesn't have support for the | 
|  | 29 | // sync framework, or if all phase offsets are zero.  The latter is useful | 
|  | 30 | // because it allows us to avoid resync bursts on devices that don't need | 
|  | 31 | // phase-offset VSYNC events. | 
|  | 32 | #if defined(RUNNING_WITHOUT_SYNC_FRAMEWORK) || \ | 
|  | 33 | (VSYNC_EVENT_PHASE_OFFSET_NS == 0 && SF_VSYNC_EVENT_PHASE_OFFSET_NS == 0) | 
|  | 34 | static const bool kIgnorePresentFences = true; | 
|  | 35 | #else | 
|  | 36 | static const bool kIgnorePresentFences = false; | 
|  | 37 | #endif | 
|  | 38 |  | 
|  | 39 |  | 
| Jamie Gennis | faf77cc | 2013-07-30 15:10:32 -0700 | [diff] [blame] | 40 | class String8; | 
|  | 41 | class Fence; | 
|  | 42 | class DispSyncThread; | 
|  | 43 |  | 
|  | 44 | // DispSync maintains a model of the periodic hardware-based vsync events of a | 
|  | 45 | // display and uses that model to execute period callbacks at specific phase | 
|  | 46 | // offsets from the hardware vsync events.  The model is constructed by | 
|  | 47 | // feeding consecutive hardware event timestamps to the DispSync object via | 
|  | 48 | // the addResyncSample method. | 
|  | 49 | // | 
|  | 50 | // The model is validated using timestamps from Fence objects that are passed | 
|  | 51 | // to the DispSync object via the addPresentFence method.  These fence | 
|  | 52 | // timestamps should correspond to a hardware vsync event, but they need not | 
|  | 53 | // be consecutive hardware vsync times.  If this method determines that the | 
|  | 54 | // current model accurately represents the hardware event times it will return | 
|  | 55 | // false to indicate that a resynchronization (via addResyncSample) is not | 
|  | 56 | // needed. | 
|  | 57 | class DispSync { | 
|  | 58 |  | 
|  | 59 | public: | 
|  | 60 |  | 
|  | 61 | class Callback: public virtual RefBase { | 
|  | 62 | public: | 
|  | 63 | virtual ~Callback() {}; | 
|  | 64 | virtual void onDispSyncEvent(nsecs_t when) = 0; | 
|  | 65 | }; | 
|  | 66 |  | 
|  | 67 | DispSync(); | 
|  | 68 | ~DispSync(); | 
|  | 69 |  | 
| Andy McFadden | 645b1f7 | 2014-06-10 14:43:32 -0700 | [diff] [blame] | 70 | // reset clears the resync samples and error value. | 
| Jamie Gennis | faf77cc | 2013-07-30 15:10:32 -0700 | [diff] [blame] | 71 | void reset(); | 
|  | 72 |  | 
|  | 73 | // addPresentFence adds a fence for use in validating the current vsync | 
|  | 74 | // event model.  The fence need not be signaled at the time | 
|  | 75 | // addPresentFence is called.  When the fence does signal, its timestamp | 
|  | 76 | // should correspond to a hardware vsync event.  Unlike the | 
|  | 77 | // addResyncSample method, the timestamps of consecutive fences need not | 
|  | 78 | // correspond to consecutive hardware vsync events. | 
|  | 79 | // | 
|  | 80 | // This method should be called with the retire fence from each HWComposer | 
|  | 81 | // set call that affects the display. | 
|  | 82 | bool addPresentFence(const sp<Fence>& fence); | 
|  | 83 |  | 
|  | 84 | // The beginResync, addResyncSample, and endResync methods are used to re- | 
|  | 85 | // synchronize the DispSync's model to the hardware vsync events.  The re- | 
|  | 86 | // synchronization process involves first calling beginResync, then | 
|  | 87 | // calling addResyncSample with a sequence of consecutive hardware vsync | 
|  | 88 | // event timestamps, and finally calling endResync when addResyncSample | 
|  | 89 | // indicates that no more samples are needed by returning false. | 
|  | 90 | // | 
|  | 91 | // This resynchronization process should be performed whenever the display | 
|  | 92 | // is turned on (i.e. once immediately after it's turned on) and whenever | 
|  | 93 | // addPresentFence returns true indicating that the model has drifted away | 
|  | 94 | // from the hardware vsync events. | 
|  | 95 | void beginResync(); | 
|  | 96 | bool addResyncSample(nsecs_t timestamp); | 
|  | 97 | void endResync(); | 
|  | 98 |  | 
| Andy McFadden | 41d67d7 | 2014-04-25 16:58:34 -0700 | [diff] [blame] | 99 | // The setPeriod method sets the vsync event model's period to a specific | 
| Jamie Gennis | faf77cc | 2013-07-30 15:10:32 -0700 | [diff] [blame] | 100 | // value.  This should be used to prime the model when a display is first | 
|  | 101 | // turned on.  It should NOT be used after that. | 
|  | 102 | void setPeriod(nsecs_t period); | 
|  | 103 |  | 
| Lajos Molnar | 67d8bd6 | 2014-09-11 14:58:45 -0700 | [diff] [blame] | 104 | // The getPeriod method returns the current vsync period. | 
|  | 105 | nsecs_t getPeriod(); | 
|  | 106 |  | 
| Andy McFadden | 645b1f7 | 2014-06-10 14:43:32 -0700 | [diff] [blame] | 107 | // setRefreshSkipCount specifies an additional number of refresh | 
|  | 108 | // cycles to skip.  For example, on a 60Hz display, a skip count of 1 | 
|  | 109 | // will result in events happening at 30Hz.  Default is zero.  The idea | 
|  | 110 | // is to sacrifice smoothness for battery life. | 
|  | 111 | void setRefreshSkipCount(int count); | 
| Ruchi Kandoi | f52b3c8 | 2014-04-24 16:42:35 -0700 | [diff] [blame] | 112 |  | 
| Jamie Gennis | faf77cc | 2013-07-30 15:10:32 -0700 | [diff] [blame] | 113 | // addEventListener registers a callback to be called repeatedly at the | 
|  | 114 | // given phase offset from the hardware vsync events.  The callback is | 
|  | 115 | // called from a separate thread and it should return reasonably quickly | 
|  | 116 | // (i.e. within a few hundred microseconds). | 
|  | 117 | status_t addEventListener(nsecs_t phase, const sp<Callback>& callback); | 
|  | 118 |  | 
|  | 119 | // removeEventListener removes an already-registered event callback.  Once | 
|  | 120 | // this method returns that callback will no longer be called by the | 
|  | 121 | // DispSync object. | 
|  | 122 | status_t removeEventListener(const sp<Callback>& callback); | 
|  | 123 |  | 
| Andy McFadden | 41d67d7 | 2014-04-25 16:58:34 -0700 | [diff] [blame] | 124 | // computeNextRefresh computes when the next refresh is expected to begin. | 
|  | 125 | // The periodOffset value can be used to move forward or backward; an | 
|  | 126 | // offset of zero is the next refresh, -1 is the previous refresh, 1 is | 
|  | 127 | // the refresh after next. etc. | 
|  | 128 | nsecs_t computeNextRefresh(int periodOffset) const; | 
|  | 129 |  | 
| Andy McFadden | c751e92 | 2014-05-08 14:53:26 -0700 | [diff] [blame] | 130 | // dump appends human-readable debug info to the result string. | 
|  | 131 | void dump(String8& result) const; | 
|  | 132 |  | 
| Jamie Gennis | faf77cc | 2013-07-30 15:10:32 -0700 | [diff] [blame] | 133 | private: | 
|  | 134 |  | 
|  | 135 | void updateModelLocked(); | 
|  | 136 | void updateErrorLocked(); | 
|  | 137 | void resetErrorLocked(); | 
|  | 138 |  | 
|  | 139 | enum { MAX_RESYNC_SAMPLES = 32 }; | 
|  | 140 | enum { MIN_RESYNC_SAMPLES_FOR_UPDATE = 3 }; | 
|  | 141 | enum { NUM_PRESENT_SAMPLES = 8 }; | 
| Dan Stoza | 9c64757 | 2015-05-29 13:00:23 -0700 | [diff] [blame^] | 142 | enum { MAX_RESYNC_SAMPLES_WITHOUT_PRESENT = 4 }; | 
| Jamie Gennis | faf77cc | 2013-07-30 15:10:32 -0700 | [diff] [blame] | 143 |  | 
|  | 144 | // mPeriod is the computed period of the modeled vsync events in | 
|  | 145 | // nanoseconds. | 
|  | 146 | nsecs_t mPeriod; | 
|  | 147 |  | 
|  | 148 | // mPhase is the phase offset of the modeled vsync events.  It is the | 
|  | 149 | // number of nanoseconds from time 0 to the first vsync event. | 
|  | 150 | nsecs_t mPhase; | 
|  | 151 |  | 
|  | 152 | // mError is the computed model error.  It is based on the difference | 
|  | 153 | // between the estimated vsync event times and those observed in the | 
|  | 154 | // mPresentTimes array. | 
|  | 155 | nsecs_t mError; | 
|  | 156 |  | 
|  | 157 | // These member variables are the state used during the resynchronization | 
|  | 158 | // process to store information about the hardware vsync event times used | 
|  | 159 | // to compute the model. | 
|  | 160 | nsecs_t mResyncSamples[MAX_RESYNC_SAMPLES]; | 
|  | 161 | size_t mFirstResyncSample; | 
|  | 162 | size_t mNumResyncSamples; | 
|  | 163 | int mNumResyncSamplesSincePresent; | 
|  | 164 |  | 
|  | 165 | // These member variables store information about the present fences used | 
|  | 166 | // to validate the currently computed model. | 
|  | 167 | sp<Fence> mPresentFences[NUM_PRESENT_SAMPLES]; | 
|  | 168 | nsecs_t mPresentTimes[NUM_PRESENT_SAMPLES]; | 
|  | 169 | size_t mPresentSampleOffset; | 
|  | 170 |  | 
| Andy McFadden | 645b1f7 | 2014-06-10 14:43:32 -0700 | [diff] [blame] | 171 | int mRefreshSkipCount; | 
|  | 172 |  | 
| Jamie Gennis | faf77cc | 2013-07-30 15:10:32 -0700 | [diff] [blame] | 173 | // mThread is the thread from which all the callbacks are called. | 
|  | 174 | sp<DispSyncThread> mThread; | 
|  | 175 |  | 
|  | 176 | // mMutex is used to protect access to all member variables. | 
|  | 177 | mutable Mutex mMutex; | 
|  | 178 | }; | 
|  | 179 |  | 
|  | 180 | } | 
|  | 181 |  | 
|  | 182 | #endif // ANDROID_DISPSYNC_H |