1ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed/*
2ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed * Copyright (C) 2010 The Android Open Source Project
3ee038351805af80e68e85eea245efec977bd30a3Naseer Ahmed * Copyright (C) 2012-2013, The Linux Foundation. All rights reserved.
4ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed *
5ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed * Not a Contribution, Apache license notifications and license are
6ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed * retained for attribution purposes only.
7ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed
8ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed * Licensed under the Apache License, Version 2.0 (the "License");
9ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed * you may not use this file except in compliance with the License.
10ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed * You may obtain a copy of the License at
11ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed *
12ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed *      http://www.apache.org/licenses/LICENSE-2.0
13ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed *
14ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed * Unless required by applicable law or agreed to in writing, software
15ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed * distributed under the License is distributed on an "AS IS" BASIS,
16ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed * See the License for the specific language governing permissions and
18ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed * limitations under the License.
19ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed */
20ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed
216bacbb6cd32f78e2670ad1213fc7541f113be921Naseer Ahmed#include <cutils/properties.h>
22ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed#include <utils/Log.h>
23ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed#include <fcntl.h>
24c7faa70f4a92f020f9d5df20a4ae4bb80be7a022Naseer Ahmed#include <sys/ioctl.h>
25c7faa70f4a92f020f9d5df20a4ae4bb80be7a022Naseer Ahmed#include <linux/msm_mdp.h>
26ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed#include <sys/resource.h>
27ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed#include <sys/prctl.h>
28ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed#include "hwc_utils.h"
29ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed#include "string.h"
30ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed#include "external.h"
31ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed
32ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmednamespace qhwc {
33ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed
340f9c397181604f28d15c9273de42f97ae2b4c613Iliyan Malchev#define HWC_VSYNC_THREAD_NAME "hwcVsyncThread"
350f9c397181604f28d15c9273de42f97ae2b4c613Iliyan Malchev
3605207f5a7575e59e5f22bb9de46f3b6b6ce2cb8dNaseer Ahmedint hwc_vsync_control(hwc_context_t* ctx, int dpy, int enable)
3705207f5a7575e59e5f22bb9de46f3b6b6ce2cb8dNaseer Ahmed{
3805207f5a7575e59e5f22bb9de46f3b6b6ce2cb8dNaseer Ahmed    int ret = 0;
3905207f5a7575e59e5f22bb9de46f3b6b6ce2cb8dNaseer Ahmed    if(!ctx->vstate.fakevsync &&
4005207f5a7575e59e5f22bb9de46f3b6b6ce2cb8dNaseer Ahmed       ioctl(ctx->dpyAttr[dpy].fd, MSMFB_OVERLAY_VSYNC_CTRL,
4105207f5a7575e59e5f22bb9de46f3b6b6ce2cb8dNaseer Ahmed             &enable) < 0) {
4205207f5a7575e59e5f22bb9de46f3b6b6ce2cb8dNaseer Ahmed        ALOGE("%s: vsync control failed. Dpy=%d, enable=%d : %s",
4305207f5a7575e59e5f22bb9de46f3b6b6ce2cb8dNaseer Ahmed              __FUNCTION__, dpy, enable, strerror(errno));
4405207f5a7575e59e5f22bb9de46f3b6b6ce2cb8dNaseer Ahmed        ret = -errno;
4505207f5a7575e59e5f22bb9de46f3b6b6ce2cb8dNaseer Ahmed    }
4605207f5a7575e59e5f22bb9de46f3b6b6ce2cb8dNaseer Ahmed    return ret;
4705207f5a7575e59e5f22bb9de46f3b6b6ce2cb8dNaseer Ahmed}
4805207f5a7575e59e5f22bb9de46f3b6b6ce2cb8dNaseer Ahmed
49ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmedstatic void *vsync_loop(void *param)
50ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed{
51ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed    const char* vsync_timestamp_fb0 = "/sys/class/graphics/fb0/vsync_event";
52ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed    const char* vsync_timestamp_fb1 = "/sys/class/graphics/fb1/vsync_event";
53c7faa70f4a92f020f9d5df20a4ae4bb80be7a022Naseer Ahmed    int dpy = HWC_DISPLAY_PRIMARY;
54ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed
55ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed    hwc_context_t * ctx = reinterpret_cast<hwc_context_t *>(param);
56ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed
570f9c397181604f28d15c9273de42f97ae2b4c613Iliyan Malchev    char thread_name[64] = HWC_VSYNC_THREAD_NAME;
58ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed    prctl(PR_SET_NAME, (unsigned long) &thread_name, 0, 0, 0);
59ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed    setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY +
60ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed                android::PRIORITY_MORE_FAVORABLE);
61ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed
624014777bab1f81db4157db7759d74478eefca22cNaseer Ahmed    const int MAX_DATA = 64;
634014777bab1f81db4157db7759d74478eefca22cNaseer Ahmed    static char vdata[MAX_DATA];
64ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed
65ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed    uint64_t cur_timestamp=0;
66eac8965bf481a17c6bca291c0864d0eb3c0eac07Iliyan Malchev    ssize_t len = -1;
67eac8965bf481a17c6bca291c0864d0eb3c0eac07Iliyan Malchev    int fd_timestamp = -1;
68c7faa70f4a92f020f9d5df20a4ae4bb80be7a022Naseer Ahmed    int ret = 0;
69ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed    bool fb1_vsync = false;
7005207f5a7575e59e5f22bb9de46f3b6b6ce2cb8dNaseer Ahmed    bool logvsync = false;
716bacbb6cd32f78e2670ad1213fc7541f113be921Naseer Ahmed
726bacbb6cd32f78e2670ad1213fc7541f113be921Naseer Ahmed    char property[PROPERTY_VALUE_MAX];
736bacbb6cd32f78e2670ad1213fc7541f113be921Naseer Ahmed    if(property_get("debug.hwc.fakevsync", property, NULL) > 0) {
746bacbb6cd32f78e2670ad1213fc7541f113be921Naseer Ahmed        if(atoi(property) == 1)
7505207f5a7575e59e5f22bb9de46f3b6b6ce2cb8dNaseer Ahmed            ctx->vstate.fakevsync = true;
7605207f5a7575e59e5f22bb9de46f3b6b6ce2cb8dNaseer Ahmed    }
7705207f5a7575e59e5f22bb9de46f3b6b6ce2cb8dNaseer Ahmed
7805207f5a7575e59e5f22bb9de46f3b6b6ce2cb8dNaseer Ahmed    if(property_get("debug.hwc.logvsync", property, 0) > 0) {
7905207f5a7575e59e5f22bb9de46f3b6b6ce2cb8dNaseer Ahmed        if(atoi(property) == 1)
8005207f5a7575e59e5f22bb9de46f3b6b6ce2cb8dNaseer Ahmed            logvsync = true;
816bacbb6cd32f78e2670ad1213fc7541f113be921Naseer Ahmed    }
82ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed
83ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed    /* Currently read vsync timestamp from drivers
84ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed       e.g. VSYNC=41800875994
856bacbb6cd32f78e2670ad1213fc7541f113be921Naseer Ahmed       */
8608212c04d2128d8967208b823c7eb4b63720de79Naseer Ahmed    fd_timestamp = open(vsync_timestamp_fb0, O_RDONLY);
8708212c04d2128d8967208b823c7eb4b63720de79Naseer Ahmed    if (fd_timestamp < 0) {
88c2f61ab1d7cc647126b30c4793d700299e90f192Naseer Ahmed        // Make sure fb device is opened before starting this thread so this
89c2f61ab1d7cc647126b30c4793d700299e90f192Naseer Ahmed        // never happens.
9008212c04d2128d8967208b823c7eb4b63720de79Naseer Ahmed        ALOGE ("FATAL:%s:not able to open file:%s, %s",  __FUNCTION__,
9108212c04d2128d8967208b823c7eb4b63720de79Naseer Ahmed               (fb1_vsync) ? vsync_timestamp_fb1 : vsync_timestamp_fb0,
9208212c04d2128d8967208b823c7eb4b63720de79Naseer Ahmed               strerror(errno));
9305207f5a7575e59e5f22bb9de46f3b6b6ce2cb8dNaseer Ahmed        ctx->vstate.fakevsync = true;
9408212c04d2128d8967208b823c7eb4b63720de79Naseer Ahmed    }
95ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed
96ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed    do {
97c2f61ab1d7cc647126b30c4793d700299e90f192Naseer Ahmed        if (LIKELY(!ctx->vstate.fakevsync)) {
98c2f61ab1d7cc647126b30c4793d700299e90f192Naseer Ahmed            len = pread(fd_timestamp, vdata, MAX_DATA, 0);
996bacbb6cd32f78e2670ad1213fc7541f113be921Naseer Ahmed            if (len < 0) {
100c2f61ab1d7cc647126b30c4793d700299e90f192Naseer Ahmed                // If the read was just interrupted - it is not a fatal error
101c2f61ab1d7cc647126b30c4793d700299e90f192Naseer Ahmed                // In either case, just continue.
102c2f61ab1d7cc647126b30c4793d700299e90f192Naseer Ahmed                if (errno != EAGAIN &&
103c2f61ab1d7cc647126b30c4793d700299e90f192Naseer Ahmed                    errno != EINTR  &&
104c2f61ab1d7cc647126b30c4793d700299e90f192Naseer Ahmed                    errno != EBUSY) {
105c2f61ab1d7cc647126b30c4793d700299e90f192Naseer Ahmed                    ALOGE ("FATAL:%s:not able to read file:%s, %s",
106c2f61ab1d7cc647126b30c4793d700299e90f192Naseer Ahmed                           __FUNCTION__,
107c2f61ab1d7cc647126b30c4793d700299e90f192Naseer Ahmed                           vsync_timestamp_fb0, strerror(errno));
108c2f61ab1d7cc647126b30c4793d700299e90f192Naseer Ahmed                }
1094df6fc1dcca26b78692c27d723c0d0de099ec103Naseer Ahmed                continue;
1106bacbb6cd32f78e2670ad1213fc7541f113be921Naseer Ahmed            }
1116bacbb6cd32f78e2670ad1213fc7541f113be921Naseer Ahmed            // extract timestamp
1126bacbb6cd32f78e2670ad1213fc7541f113be921Naseer Ahmed            const char *str = vdata;
1136bacbb6cd32f78e2670ad1213fc7541f113be921Naseer Ahmed            if (!strncmp(str, "VSYNC=", strlen("VSYNC="))) {
1146bacbb6cd32f78e2670ad1213fc7541f113be921Naseer Ahmed                cur_timestamp = strtoull(str + strlen("VSYNC="), NULL, 0);
1156bacbb6cd32f78e2670ad1213fc7541f113be921Naseer Ahmed            }
1166bacbb6cd32f78e2670ad1213fc7541f113be921Naseer Ahmed        } else {
117c2f61ab1d7cc647126b30c4793d700299e90f192Naseer Ahmed            usleep(16666);
1186bacbb6cd32f78e2670ad1213fc7541f113be921Naseer Ahmed            cur_timestamp = systemTime();
1196bacbb6cd32f78e2670ad1213fc7541f113be921Naseer Ahmed        }
1206bacbb6cd32f78e2670ad1213fc7541f113be921Naseer Ahmed        // send timestamp to HAL
12120cec8421c5211c2e5f2501f4eda5b834c4f766bNaseer Ahmed        if(ctx->vstate.enable) {
12220cec8421c5211c2e5f2501f4eda5b834c4f766bNaseer Ahmed            ALOGD_IF (logvsync, "%s: timestamp %llu sent to HWC for %s",
12320cec8421c5211c2e5f2501f4eda5b834c4f766bNaseer Ahmed                      __FUNCTION__, cur_timestamp, "fb0");
12420cec8421c5211c2e5f2501f4eda5b834c4f766bNaseer Ahmed            ctx->proc->vsync(ctx->proc, dpy, cur_timestamp);
12520cec8421c5211c2e5f2501f4eda5b834c4f766bNaseer Ahmed        }
126ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed
127ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed    } while (true);
1284014777bab1f81db4157db7759d74478eefca22cNaseer Ahmed    if(fd_timestamp >= 0)
1294014777bab1f81db4157db7759d74478eefca22cNaseer Ahmed        close (fd_timestamp);
130eac8965bf481a17c6bca291c0864d0eb3c0eac07Iliyan Malchev
131eac8965bf481a17c6bca291c0864d0eb3c0eac07Iliyan Malchev    return NULL;
132ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed}
133ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed
134ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmedvoid init_vsync_thread(hwc_context_t* ctx)
135ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed{
1360f9c397181604f28d15c9273de42f97ae2b4c613Iliyan Malchev    int ret;
137ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed    pthread_t vsync_thread;
138ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed    ALOGI("Initializing VSYNC Thread");
1390f9c397181604f28d15c9273de42f97ae2b4c613Iliyan Malchev    ret = pthread_create(&vsync_thread, NULL, vsync_loop, (void*) ctx);
1400f9c397181604f28d15c9273de42f97ae2b4c613Iliyan Malchev    if (ret) {
1410f9c397181604f28d15c9273de42f97ae2b4c613Iliyan Malchev        ALOGE("%s: failed to create %s: %s", __FUNCTION__,
1426bacbb6cd32f78e2670ad1213fc7541f113be921Naseer Ahmed              HWC_VSYNC_THREAD_NAME, strerror(ret));
1430f9c397181604f28d15c9273de42f97ae2b4c613Iliyan Malchev    }
144ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed}
145ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed
146ff4f0254be575a264504687c407e0db2fd5573d7Naseer Ahmed}; //namespace
147