Home | History | Annotate | Download | only in surfaceflinger
      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 
     28 // Ignore present (retire) fences if the device doesn't have support for the
     29 // sync framework
     30 #if defined(RUNNING_WITHOUT_SYNC_FRAMEWORK)
     31 static const bool kIgnorePresentFences = true;
     32 #else
     33 static const bool kIgnorePresentFences = false;
     34 #endif
     35 
     36 
     37 class String8;
     38 class Fence;
     39 class DispSyncThread;
     40 
     41 // DispSync maintains a model of the periodic hardware-based vsync events of a
     42 // display and uses that model to execute period callbacks at specific phase
     43 // offsets from the hardware vsync events.  The model is constructed by
     44 // feeding consecutive hardware event timestamps to the DispSync object via
     45 // the addResyncSample method.
     46 //
     47 // The model is validated using timestamps from Fence objects that are passed
     48 // to the DispSync object via the addPresentFence method.  These fence
     49 // timestamps should correspond to a hardware vsync event, but they need not
     50 // be consecutive hardware vsync times.  If this method determines that the
     51 // current model accurately represents the hardware event times it will return
     52 // false to indicate that a resynchronization (via addResyncSample) is not
     53 // needed.
     54 class DispSync {
     55 
     56 public:
     57 
     58     class Callback: public virtual RefBase {
     59     public:
     60         virtual ~Callback() {};
     61         virtual void onDispSyncEvent(nsecs_t when) = 0;
     62     };
     63 
     64     DispSync(const char* name);
     65     ~DispSync();
     66 
     67     // reset clears the resync samples and error value.
     68     void reset();
     69 
     70     // addPresentFence adds a fence for use in validating the current vsync
     71     // event model.  The fence need not be signaled at the time
     72     // addPresentFence is called.  When the fence does signal, its timestamp
     73     // should correspond to a hardware vsync event.  Unlike the
     74     // addResyncSample method, the timestamps of consecutive fences need not
     75     // correspond to consecutive hardware vsync events.
     76     //
     77     // This method should be called with the retire fence from each HWComposer
     78     // set call that affects the display.
     79     bool addPresentFence(const sp<Fence>& fence);
     80 
     81     // The beginResync, addResyncSample, and endResync methods are used to re-
     82     // synchronize the DispSync's model to the hardware vsync events.  The re-
     83     // synchronization process involves first calling beginResync, then
     84     // calling addResyncSample with a sequence of consecutive hardware vsync
     85     // event timestamps, and finally calling endResync when addResyncSample
     86     // indicates that no more samples are needed by returning false.
     87     //
     88     // This resynchronization process should be performed whenever the display
     89     // is turned on (i.e. once immediately after it's turned on) and whenever
     90     // addPresentFence returns true indicating that the model has drifted away
     91     // from the hardware vsync events.
     92     void beginResync();
     93     bool addResyncSample(nsecs_t timestamp);
     94     void endResync();
     95 
     96     // The setPeriod method sets the vsync event model's period to a specific
     97     // value.  This should be used to prime the model when a display is first
     98     // turned on.  It should NOT be used after that.
     99     void setPeriod(nsecs_t period);
    100 
    101     // The getPeriod method returns the current vsync period.
    102     nsecs_t getPeriod();
    103 
    104     // setRefreshSkipCount specifies an additional number of refresh
    105     // cycles to skip.  For example, on a 60Hz display, a skip count of 1
    106     // will result in events happening at 30Hz.  Default is zero.  The idea
    107     // is to sacrifice smoothness for battery life.
    108     void setRefreshSkipCount(int count);
    109 
    110     // addEventListener registers a callback to be called repeatedly at the
    111     // given phase offset from the hardware vsync events.  The callback is
    112     // called from a separate thread and it should return reasonably quickly
    113     // (i.e. within a few hundred microseconds).
    114     status_t addEventListener(const char* name, nsecs_t phase,
    115             const sp<Callback>& callback);
    116 
    117     // removeEventListener removes an already-registered event callback.  Once
    118     // this method returns that callback will no longer be called by the
    119     // DispSync object.
    120     status_t removeEventListener(const sp<Callback>& callback);
    121 
    122     // computeNextRefresh computes when the next refresh is expected to begin.
    123     // The periodOffset value can be used to move forward or backward; an
    124     // offset of zero is the next refresh, -1 is the previous refresh, 1 is
    125     // the refresh after next. etc.
    126     nsecs_t computeNextRefresh(int periodOffset) const;
    127 
    128     // dump appends human-readable debug info to the result string.
    129     void dump(String8& result) const;
    130 
    131 private:
    132 
    133     void updateModelLocked();
    134     void updateErrorLocked();
    135     void resetErrorLocked();
    136 
    137     enum { MAX_RESYNC_SAMPLES = 32 };
    138     enum { MIN_RESYNC_SAMPLES_FOR_UPDATE = 6 };
    139     enum { NUM_PRESENT_SAMPLES = 8 };
    140     enum { MAX_RESYNC_SAMPLES_WITHOUT_PRESENT = 4 };
    141 
    142     const char* const mName;
    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     // mReferenceTime is the reference time of the modeled vsync events.
    153     // It is the nanosecond timestamp of the first vsync event after a resync.
    154     nsecs_t mReferenceTime;
    155 
    156     // mError is the computed model error.  It is based on the difference
    157     // between the estimated vsync event times and those observed in the
    158     // mPresentTimes array.
    159     nsecs_t mError;
    160 
    161     // Whether we have updated the vsync event model since the last resync.
    162     bool mModelUpdated;
    163 
    164     // These member variables are the state used during the resynchronization
    165     // process to store information about the hardware vsync event times used
    166     // to compute the model.
    167     nsecs_t mResyncSamples[MAX_RESYNC_SAMPLES];
    168     size_t mFirstResyncSample;
    169     size_t mNumResyncSamples;
    170     int mNumResyncSamplesSincePresent;
    171 
    172     // These member variables store information about the present fences used
    173     // to validate the currently computed model.
    174     sp<Fence> mPresentFences[NUM_PRESENT_SAMPLES];
    175     nsecs_t mPresentTimes[NUM_PRESENT_SAMPLES];
    176     size_t mPresentSampleOffset;
    177 
    178     int mRefreshSkipCount;
    179 
    180     // mThread is the thread from which all the callbacks are called.
    181     sp<DispSyncThread> mThread;
    182 
    183     // mMutex is used to protect access to all member variables.
    184     mutable Mutex mMutex;
    185 };
    186 
    187 }
    188 
    189 #endif // ANDROID_DISPSYNC_H
    190