1/*
2// Copyright (c) 2014 Intel Corporation 
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#include <common/utils/HwcTrace.h>
17#include <common/observers/SoftVsyncObserver.h>
18#include <IDisplayDevice.h>
19#include <time.h>
20
21namespace android {
22namespace intel {
23
24SoftVsyncObserver::SoftVsyncObserver(IDisplayDevice& disp)
25    : mDisplayDevice(disp),
26      mDevice(IDisplayDevice::DEVICE_COUNT),
27      mEnabled(false),
28      mRefreshRate(60), // default 60 frames per second
29      mRefreshPeriod(0),
30      mLock(),
31      mCondition(),
32      mNextFakeVSync(0),
33      mExitThread(false),
34      mInitialized(false)
35{
36}
37
38SoftVsyncObserver::~SoftVsyncObserver()
39{
40    WARN_IF_NOT_DEINIT();
41}
42
43bool SoftVsyncObserver::initialize()
44{
45    if (mInitialized) {
46        WLOGTRACE("object has been initialized");
47        return true;
48    }
49
50    mExitThread = false;
51    mEnabled = false;
52    mRefreshRate = 60;
53    mDevice = mDisplayDevice.getType();
54    mThread = new VsyncEventPollThread(this);
55    if (!mThread.get()) {
56        DEINIT_AND_RETURN_FALSE("failed to create vsync event poll thread.");
57    }
58    mThread->run("SoftVsyncObserver", PRIORITY_URGENT_DISPLAY);
59    mInitialized = true;
60    return true;
61}
62
63void SoftVsyncObserver::deinitialize()
64{
65    if (mEnabled) {
66        WLOGTRACE("soft vsync is still enabled");
67        control(false);
68    }
69
70    mExitThread = true;
71    mCondition.signal();
72
73    if (mThread.get()) {
74        mThread->requestExitAndWait();
75        mThread = NULL;
76    }
77    mInitialized = false;
78}
79
80void SoftVsyncObserver::setRefreshRate(int rate)
81{
82    if (mEnabled) {
83        WLOGTRACE("too late to set refresh rate");
84    } else if (rate < 1 || rate > 120) {
85        WLOGTRACE("invalid refresh rate %d", rate);
86    } else {
87        mRefreshRate = rate;
88    }
89}
90
91bool SoftVsyncObserver::control(bool enabled)
92{
93    if (enabled == mEnabled) {
94        WLOGTRACE("vsync state %d is not changed", enabled);
95        return true;
96    }
97
98    if (enabled) {
99        mRefreshPeriod = nsecs_t(1e9 / mRefreshRate);
100        mNextFakeVSync = systemTime(CLOCK_MONOTONIC) + mRefreshPeriod;
101    }
102    mEnabled = enabled;
103    mCondition.signal();
104    return true;
105}
106
107bool SoftVsyncObserver::threadLoop()
108{
109    { // scope for lock
110        Mutex::Autolock _l(mLock);
111        while (!mEnabled) {
112            mCondition.wait(mLock);
113            if (mExitThread) {
114                ILOGTRACE("exiting thread loop");
115                return false;
116            }
117        }
118    }
119
120
121    const nsecs_t period = mRefreshPeriod;
122    const nsecs_t now = systemTime(CLOCK_MONOTONIC);
123    nsecs_t next_vsync = mNextFakeVSync;
124    nsecs_t sleep = next_vsync - now;
125    if (sleep < 0) {
126        // we missed, find where the next vsync should be
127        sleep = (period - ((now - next_vsync) % period));
128        next_vsync = now + sleep;
129    }
130    mNextFakeVSync = next_vsync + period;
131
132    struct timespec spec;
133    spec.tv_sec  = next_vsync / 1000000000;
134    spec.tv_nsec = next_vsync % 1000000000;
135
136    int err;
137    do {
138        err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &spec, NULL);
139    } while (err < 0 && errno == EINTR);
140
141
142    if (err == 0) {
143        mDisplayDevice.onVsync(next_vsync);
144    }
145
146    return true;
147}
148
149} // namespace intel
150} // namesapce android
151
152