18b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol/*
28b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol// Copyright (c) 2014 Intel Corporation 
38b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol//
48b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol// Licensed under the Apache License, Version 2.0 (the "License");
58b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol// you may not use this file except in compliance with the License.
68b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol// You may obtain a copy of the License at
78b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol//
88b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol//      http://www.apache.org/licenses/LICENSE-2.0
98b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol//
108b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol// Unless required by applicable law or agreed to in writing, software
118b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol// distributed under the License is distributed on an "AS IS" BASIS,
128b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol// See the License for the specific language governing permissions and
148b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol// limitations under the License.
158b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol*/
168b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol#include <HwcTrace.h>
178b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol#include <SoftVsyncObserver.h>
188b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol#include <IDisplayDevice.h>
198b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
208b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolextern "C" int clock_nanosleep(clockid_t clock_id, int flags,
218b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol                           const struct timespec *request,
228b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol                           struct timespec *remain);
238b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
248b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
258b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolnamespace android {
268b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolnamespace intel {
278b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
288b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin PujolSoftVsyncObserver::SoftVsyncObserver(IDisplayDevice& disp)
298b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    : mDisplayDevice(disp),
308b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol      mDevice(IDisplayDevice::DEVICE_COUNT),
318b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol      mEnabled(false),
328b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol      mRefreshRate(60), // default 60 frames per second
338b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol      mRefreshPeriod(0),
348b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol      mLock(),
358b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol      mCondition(),
368b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol      mNextFakeVSync(0),
378b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol      mExitThread(false),
388b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol      mInitialized(false)
398b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{
408b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol}
418b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
428b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin PujolSoftVsyncObserver::~SoftVsyncObserver()
438b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{
448b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    WARN_IF_NOT_DEINIT();
458b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol}
468b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
478b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolbool SoftVsyncObserver::initialize()
488b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{
498b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (mInitialized) {
508b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        WTRACE("object has been initialized");
518b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return true;
528b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
538b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
548b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    mExitThread = false;
558b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    mEnabled = false;
568b55c41553ee026c299578b158c4b85de50aaee1Victor Tasayco Loarte    mRefreshRate = 60/mDisplayDevice.getFpsDivider();
578b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    mDevice = mDisplayDevice.getType();
588b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    mThread = new VsyncEventPollThread(this);
598b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (!mThread.get()) {
608b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        DEINIT_AND_RETURN_FALSE("failed to create vsync event poll thread.");
618b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
628b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    mThread->run("SoftVsyncObserver", PRIORITY_URGENT_DISPLAY);
638b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    mInitialized = true;
648b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    return true;
658b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol}
668b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
678b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolvoid SoftVsyncObserver::deinitialize()
688b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{
698b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (mEnabled) {
708b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        WTRACE("soft vsync is still enabled");
718b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        control(false);
728b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
738b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
748b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    mExitThread = true;
758b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    mCondition.signal();
768b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
778b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (mThread.get()) {
788b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        mThread->requestExitAndWait();
798b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        mThread = NULL;
808b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
818b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    mInitialized = false;
828b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol}
838b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
848b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolvoid SoftVsyncObserver::setRefreshRate(int rate)
858b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{
868b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (mEnabled) {
878b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        WTRACE("too late to set refresh rate");
888b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    } else if (rate < 1 || rate > 120) {
898b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        WTRACE("invalid refresh rate %d", rate);
908b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    } else {
918b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        mRefreshRate = rate;
928b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
938b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol}
948b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
958b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolbool SoftVsyncObserver::control(bool enabled)
968b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{
978b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (enabled == mEnabled) {
988b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        WTRACE("vsync state %d is not changed", enabled);
998b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return true;
1008b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
1018b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
1028b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (enabled) {
1038b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        mRefreshPeriod = nsecs_t(1e9 / mRefreshRate);
1048b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        mNextFakeVSync = systemTime(CLOCK_MONOTONIC) + mRefreshPeriod;
1058b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
1068b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    mEnabled = enabled;
1078b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    mCondition.signal();
1088b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    return true;
1098b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol}
1108b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
1118b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolbool SoftVsyncObserver::threadLoop()
1128b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{
1138b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    { // scope for lock
1148b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        Mutex::Autolock _l(mLock);
1158b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        while (!mEnabled) {
1168b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            mCondition.wait(mLock);
1178b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            if (mExitThread) {
1188b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol                ITRACE("exiting thread loop");
1198b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol                return false;
1208b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            }
1218b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        }
1228b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
1238b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
1248b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
1258b55c41553ee026c299578b158c4b85de50aaee1Victor Tasayco Loarte    const nsecs_t period = mRefreshPeriod * mDisplayDevice.getFpsDivider();
1268b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    const nsecs_t now = systemTime(CLOCK_MONOTONIC);
1278b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    nsecs_t next_vsync = mNextFakeVSync;
1288b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    nsecs_t sleep = next_vsync - now;
1298b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (sleep < 0) {
1308b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        // we missed, find where the next vsync should be
1318b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        sleep = (period - ((now - next_vsync) % period));
1328b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        next_vsync = now + sleep;
1338b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
1348b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    mNextFakeVSync = next_vsync + period;
1358b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
1368b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    struct timespec spec;
1378b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    spec.tv_sec  = next_vsync / 1000000000;
1388b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    spec.tv_nsec = next_vsync % 1000000000;
1398b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
1408b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    int err;
1418b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    do {
1428b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &spec, NULL);
1438b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    } while (err < 0 && errno == EINTR);
1448b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
1458b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
1468b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (err == 0) {
1478b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        mDisplayDevice.onVsync(next_vsync);
1488b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
1498b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
1508b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    return true;
1518b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol}
1528b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
1538b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol} // namespace intel
1548b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol} // namesapce android
1558b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
156