1faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis/* 2faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis * Copyright (C) 2012 The Android Open Source Project 3faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis * 4faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis * Licensed under the Apache License, Version 2.0 (the "License"); 5faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis * you may not use this file except in compliance with the License. 6faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis * You may obtain a copy of the License at 7faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis * 8faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis * http://www.apache.org/licenses/LICENSE-2.0 9faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis * 10faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis * Unless required by applicable law or agreed to in writing, software 11faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis * distributed under the License is distributed on an "AS IS" BASIS, 12faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis * See the License for the specific language governing permissions and 14faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis * limitations under the License. 15faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis */ 16faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis 17faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis#ifndef ANDROID_DISPSYNC_H 18faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis#define ANDROID_DISPSYNC_H 19faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis 20faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis#include <stddef.h> 21faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis 22faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis#include <utils/Mutex.h> 23faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis#include <utils/Timers.h> 24faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis#include <utils/RefBase.h> 25faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis 26fbc80aef0ba1b11982cf4ca88d218b65b6eca0f3Brian Anderson#include <ui/FenceTime.h> 27fbc80aef0ba1b11982cf4ca88d218b65b6eca0f3Brian Anderson 28fbc80aef0ba1b11982cf4ca88d218b65b6eca0f3Brian Anderson#include <memory> 29fbc80aef0ba1b11982cf4ca88d218b65b6eca0f3Brian Anderson 30faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennisnamespace android { 31faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis 32faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennisclass String8; 33fbc80aef0ba1b11982cf4ca88d218b65b6eca0f3Brian Andersonclass FenceTime; 34faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennisclass DispSyncThread; 35faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis 36faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis// DispSync maintains a model of the periodic hardware-based vsync events of a 37faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis// display and uses that model to execute period callbacks at specific phase 38faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis// offsets from the hardware vsync events. The model is constructed by 39faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis// feeding consecutive hardware event timestamps to the DispSync object via 40faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis// the addResyncSample method. 41faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis// 42faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis// The model is validated using timestamps from Fence objects that are passed 43faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis// to the DispSync object via the addPresentFence method. These fence 44faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis// timestamps should correspond to a hardware vsync event, but they need not 45faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis// be consecutive hardware vsync times. If this method determines that the 46faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis// current model accurately represents the hardware event times it will return 47faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis// false to indicate that a resynchronization (via addResyncSample) is not 48faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis// needed. 49faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennisclass DispSync { 50faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis 51faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennispublic: 52faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis 53faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis class Callback: public virtual RefBase { 54faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis public: 55faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis virtual ~Callback() {}; 56faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis virtual void onDispSyncEvent(nsecs_t when) = 0; 57faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis }; 58faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis 59342b760763300593cd20b01dac8cef61e7b25b86Chih-Hung Hsieh explicit DispSync(const char* name); 60faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis ~DispSync(); 61faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis 62f41745301d5ecfa680dcef3a1948a8a321f80509Saurabh Shah void init(bool hasSyncFramework, int64_t dispSyncPresentTimeOffset); 63f41745301d5ecfa680dcef3a1948a8a321f80509Saurabh Shah 64645b1f7ffb41d21a60765d1ec54ba82f14a36a59Andy McFadden // reset clears the resync samples and error value. 65faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis void reset(); 66faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis 67faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis // addPresentFence adds a fence for use in validating the current vsync 68faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis // event model. The fence need not be signaled at the time 69faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis // addPresentFence is called. When the fence does signal, its timestamp 70faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis // should correspond to a hardware vsync event. Unlike the 71faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis // addResyncSample method, the timestamps of consecutive fences need not 72faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis // correspond to consecutive hardware vsync events. 73faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis // 74faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis // This method should be called with the retire fence from each HWComposer 75faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis // set call that affects the display. 76fbc80aef0ba1b11982cf4ca88d218b65b6eca0f3Brian Anderson bool addPresentFence(const std::shared_ptr<FenceTime>& fenceTime); 77faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis 78faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis // The beginResync, addResyncSample, and endResync methods are used to re- 79faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis // synchronize the DispSync's model to the hardware vsync events. The re- 80faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis // synchronization process involves first calling beginResync, then 81faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis // calling addResyncSample with a sequence of consecutive hardware vsync 82faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis // event timestamps, and finally calling endResync when addResyncSample 83faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis // indicates that no more samples are needed by returning false. 84faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis // 85faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis // This resynchronization process should be performed whenever the display 86faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis // is turned on (i.e. once immediately after it's turned on) and whenever 87faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis // addPresentFence returns true indicating that the model has drifted away 88faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis // from the hardware vsync events. 89faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis void beginResync(); 90faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis bool addResyncSample(nsecs_t timestamp); 91faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis void endResync(); 92faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis 9341d67d7ab4da1c393497a620a116a854b3c618e7Andy McFadden // The setPeriod method sets the vsync event model's period to a specific 94faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis // value. This should be used to prime the model when a display is first 95faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis // turned on. It should NOT be used after that. 96faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis void setPeriod(nsecs_t period); 97faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis 9867d8bd66aaf04805cb8f2616ba964141b865e3b9Lajos Molnar // The getPeriod method returns the current vsync period. 9967d8bd66aaf04805cb8f2616ba964141b865e3b9Lajos Molnar nsecs_t getPeriod(); 10067d8bd66aaf04805cb8f2616ba964141b865e3b9Lajos Molnar 101645b1f7ffb41d21a60765d1ec54ba82f14a36a59Andy McFadden // setRefreshSkipCount specifies an additional number of refresh 102645b1f7ffb41d21a60765d1ec54ba82f14a36a59Andy McFadden // cycles to skip. For example, on a 60Hz display, a skip count of 1 103645b1f7ffb41d21a60765d1ec54ba82f14a36a59Andy McFadden // will result in events happening at 30Hz. Default is zero. The idea 104645b1f7ffb41d21a60765d1ec54ba82f14a36a59Andy McFadden // is to sacrifice smoothness for battery life. 105645b1f7ffb41d21a60765d1ec54ba82f14a36a59Andy McFadden void setRefreshSkipCount(int count); 106f52b3c88f18c0546526996c839fbce74172e11c7Ruchi Kandoi 107faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis // addEventListener registers a callback to be called repeatedly at the 108faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis // given phase offset from the hardware vsync events. The callback is 109faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis // called from a separate thread and it should return reasonably quickly 110faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis // (i.e. within a few hundred microseconds). 1114a4e4a239f034cb8af2df9a438b26c3bc088889cTim Murray status_t addEventListener(const char* name, nsecs_t phase, 1124a4e4a239f034cb8af2df9a438b26c3bc088889cTim Murray const sp<Callback>& callback); 113faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis 114faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis // removeEventListener removes an already-registered event callback. Once 115faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis // this method returns that callback will no longer be called by the 116faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis // DispSync object. 117faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis status_t removeEventListener(const sp<Callback>& callback); 118faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis 11941d67d7ab4da1c393497a620a116a854b3c618e7Andy McFadden // computeNextRefresh computes when the next refresh is expected to begin. 12041d67d7ab4da1c393497a620a116a854b3c618e7Andy McFadden // The periodOffset value can be used to move forward or backward; an 12141d67d7ab4da1c393497a620a116a854b3c618e7Andy McFadden // offset of zero is the next refresh, -1 is the previous refresh, 1 is 12241d67d7ab4da1c393497a620a116a854b3c618e7Andy McFadden // the refresh after next. etc. 12341d67d7ab4da1c393497a620a116a854b3c618e7Andy McFadden nsecs_t computeNextRefresh(int periodOffset) const; 12441d67d7ab4da1c393497a620a116a854b3c618e7Andy McFadden 125c751e92c56de5f335a36e68607c7a6c627dcd0dcAndy McFadden // dump appends human-readable debug info to the result string. 126c751e92c56de5f335a36e68607c7a6c627dcd0dcAndy McFadden void dump(String8& result) const; 127c751e92c56de5f335a36e68607c7a6c627dcd0dcAndy McFadden 128faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennisprivate: 129faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis 130faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis void updateModelLocked(); 131faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis void updateErrorLocked(); 132faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis void resetErrorLocked(); 133faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis 134faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis enum { MAX_RESYNC_SAMPLES = 32 }; 1354a4e4a239f034cb8af2df9a438b26c3bc088889cTim Murray enum { MIN_RESYNC_SAMPLES_FOR_UPDATE = 6 }; 136faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis enum { NUM_PRESENT_SAMPLES = 8 }; 137ef78916d86fa60e08a6358af4b0b1f6bd0134164Dan Stoza enum { MAX_RESYNC_SAMPLES_WITHOUT_PRESENT = 4 }; 138fbc80aef0ba1b11982cf4ca88d218b65b6eca0f3Brian Anderson enum { ACCEPTABLE_ZERO_ERR_SAMPLES_COUNT = 64 }; 139faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis 1404a4e4a239f034cb8af2df9a438b26c3bc088889cTim Murray const char* const mName; 1414a4e4a239f034cb8af2df9a438b26c3bc088889cTim Murray 142faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis // mPeriod is the computed period of the modeled vsync events in 143faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis // nanoseconds. 144faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis nsecs_t mPeriod; 145faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis 146faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis // mPhase is the phase offset of the modeled vsync events. It is the 147faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis // number of nanoseconds from time 0 to the first vsync event. 148faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis nsecs_t mPhase; 149faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis 150676b1f6ed0d637b7eb1858361e0d09068f26e9faHaixia Shi // mReferenceTime is the reference time of the modeled vsync events. 151676b1f6ed0d637b7eb1858361e0d09068f26e9faHaixia Shi // It is the nanosecond timestamp of the first vsync event after a resync. 152676b1f6ed0d637b7eb1858361e0d09068f26e9faHaixia Shi nsecs_t mReferenceTime; 153676b1f6ed0d637b7eb1858361e0d09068f26e9faHaixia Shi 154faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis // mError is the computed model error. It is based on the difference 155faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis // between the estimated vsync event times and those observed in the 156fbc80aef0ba1b11982cf4ca88d218b65b6eca0f3Brian Anderson // mPresentFences array. 157faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis nsecs_t mError; 158faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis 159fbc80aef0ba1b11982cf4ca88d218b65b6eca0f3Brian Anderson // mZeroErrSamplesCount keeps track of how many times in a row there were 160fbc80aef0ba1b11982cf4ca88d218b65b6eca0f3Brian Anderson // zero timestamps available in the mPresentFences array. 161fbc80aef0ba1b11982cf4ca88d218b65b6eca0f3Brian Anderson // Used to sanity check that we are able to calculate the model error. 162fbc80aef0ba1b11982cf4ca88d218b65b6eca0f3Brian Anderson size_t mZeroErrSamplesCount; 163fbc80aef0ba1b11982cf4ca88d218b65b6eca0f3Brian Anderson 164676b1f6ed0d637b7eb1858361e0d09068f26e9faHaixia Shi // Whether we have updated the vsync event model since the last resync. 165676b1f6ed0d637b7eb1858361e0d09068f26e9faHaixia Shi bool mModelUpdated; 166676b1f6ed0d637b7eb1858361e0d09068f26e9faHaixia Shi 167faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis // These member variables are the state used during the resynchronization 168faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis // process to store information about the hardware vsync event times used 169faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis // to compute the model. 170faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis nsecs_t mResyncSamples[MAX_RESYNC_SAMPLES]; 171faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis size_t mFirstResyncSample; 172faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis size_t mNumResyncSamples; 173faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis int mNumResyncSamplesSincePresent; 174faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis 175faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis // These member variables store information about the present fences used 176faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis // to validate the currently computed model. 177fbc80aef0ba1b11982cf4ca88d218b65b6eca0f3Brian Anderson std::shared_ptr<FenceTime> 178fbc80aef0ba1b11982cf4ca88d218b65b6eca0f3Brian Anderson mPresentFences[NUM_PRESENT_SAMPLES] {FenceTime::NO_FENCE}; 179faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis size_t mPresentSampleOffset; 180faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis 181645b1f7ffb41d21a60765d1ec54ba82f14a36a59Andy McFadden int mRefreshSkipCount; 182645b1f7ffb41d21a60765d1ec54ba82f14a36a59Andy McFadden 183faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis // mThread is the thread from which all the callbacks are called. 184faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis sp<DispSyncThread> mThread; 185faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis 186faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis // mMutex is used to protect access to all member variables. 187faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis mutable Mutex mMutex; 188c45a7d9dfdefa07512c5acc07bcbee5362b34e3dFabien Sanglard 189c45a7d9dfdefa07512c5acc07bcbee5362b34e3dFabien Sanglard // This is the offset from the present fence timestamps to the corresponding 190c45a7d9dfdefa07512c5acc07bcbee5362b34e3dFabien Sanglard // vsync event. 191c45a7d9dfdefa07512c5acc07bcbee5362b34e3dFabien Sanglard int64_t mPresentTimeOffset; 192cbf153bedf2eafc1443bbc97c4e74f97e7973eddFabien Sanglard 193cbf153bedf2eafc1443bbc97c4e74f97e7973eddFabien Sanglard // Ignore present (retire) fences if the device doesn't have support for the 194cbf153bedf2eafc1443bbc97c4e74f97e7973eddFabien Sanglard // sync framework 195cbf153bedf2eafc1443bbc97c4e74f97e7973eddFabien Sanglard bool mIgnorePresentFences; 196faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis}; 197faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis 198faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis} 199faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis 200faf77cce9d9ec0238d6999b3bd0d40c71ff403c5Jamie Gennis#endif // ANDROID_DISPSYNC_H 201