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, 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 
     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 
     70     // reset clears the resync samples and error value.
     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 
     99     // The setPeriod method sets the vsync event model's period to a specific
    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 
    104     // The getPeriod method returns the current vsync period.
    105     nsecs_t getPeriod();
    106 
    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);
    112 
    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 
    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 
    130     // dump appends human-readable debug info to the result string.
    131     void dump(String8& result) const;
    132 
    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 };
    142     enum { MAX_RESYNC_SAMPLES_WITHOUT_PRESENT = 12 };
    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 
    171     int mRefreshSkipCount;
    172 
    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
    183