• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  * Copyright (C) 2012, Code Aurora Forum. All rights reserved.
4  *
5  * Not a Contribution, Apache license notifications and license are
6  * retained for attribution purposes only.
7 
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20 
21 // WARNING : Excessive logging, if VSYNC_DEBUG enabled
22 #define VSYNC_DEBUG 0
23 
24 #include <cutils/properties.h>
25 #include <utils/Log.h>
26 #include <fcntl.h>
27 #include <sys/ioctl.h>
28 #include <linux/msm_mdp.h>
29 #include <sys/resource.h>
30 #include <sys/prctl.h>
31 #include "hwc_utils.h"
32 #include "string.h"
33 #include "external.h"
34 
35 
36 namespace qhwc {
37 
38 #define HWC_VSYNC_THREAD_NAME "hwcVsyncThread"
39 
vsync_loop(void * param)40 static void *vsync_loop(void *param)
41 {
42     const char* vsync_timestamp_fb0 = "/sys/class/graphics/fb0/vsync_event";
43     const char* vsync_timestamp_fb1 = "/sys/class/graphics/fb1/vsync_event";
44     int dpy = HWC_DISPLAY_PRIMARY;
45 
46     hwc_context_t * ctx = reinterpret_cast<hwc_context_t *>(param);
47 
48     char thread_name[64] = HWC_VSYNC_THREAD_NAME;
49     prctl(PR_SET_NAME, (unsigned long) &thread_name, 0, 0, 0);
50     setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY +
51                 android::PRIORITY_MORE_FAVORABLE);
52 
53     const int MAX_DATA = 64;
54     const int MAX_RETRY_COUNT = 100;
55     static char vdata[MAX_DATA];
56 
57     uint64_t cur_timestamp=0;
58     ssize_t len = -1;
59     int fd_timestamp = -1;
60     int ret = 0;
61     bool fb1_vsync = false;
62     bool enabled = false;
63     bool fakevsync = false;
64 
65     char property[PROPERTY_VALUE_MAX];
66     if(property_get("debug.hwc.fakevsync", property, NULL) > 0) {
67         if(atoi(property) == 1)
68             fakevsync = true;
69     }
70 
71     /* Currently read vsync timestamp from drivers
72        e.g. VSYNC=41800875994
73        */
74     fd_timestamp = open(vsync_timestamp_fb0, O_RDONLY);
75     if (fd_timestamp < 0) {
76         ALOGE ("FATAL:%s:not able to open file:%s, %s",  __FUNCTION__,
77                (fb1_vsync) ? vsync_timestamp_fb1 : vsync_timestamp_fb0,
78                strerror(errno));
79         fakevsync = true;
80     }
81 
82     do {
83         pthread_mutex_lock(&ctx->vstate.lock);
84         while (ctx->vstate.enable == false) {
85             if(enabled) {
86                 int e = 0;
87                 if(!fakevsync &&
88                    ioctl(ctx->dpyAttr[dpy].fd, MSMFB_OVERLAY_VSYNC_CTRL,
89                          &e) < 0) {
90                     ALOGE("%s: vsync control failed. Dpy=%d, enabled=%d : %s",
91                           __FUNCTION__, dpy, enabled, strerror(errno));
92                     ret = -errno;
93                 }
94                 enabled = false;
95             }
96             pthread_cond_wait(&ctx->vstate.cond, &ctx->vstate.lock);
97         }
98         pthread_mutex_unlock(&ctx->vstate.lock);
99 
100         if (!enabled) {
101             int e = 1;
102             if(!fakevsync &&
103                ioctl(ctx->dpyAttr[dpy].fd, MSMFB_OVERLAY_VSYNC_CTRL,
104                      &e) < 0) {
105                 ALOGE("%s: vsync control failed. Dpy=%d, enabled=%d : %s",
106                       __FUNCTION__, dpy, enabled, strerror(errno));
107                 ret = -errno;
108             }
109             enabled = true;
110         }
111 
112         if(!fakevsync) {
113             for(int i = 0; i < MAX_RETRY_COUNT; i++) {
114                 len = pread(fd_timestamp, vdata, MAX_DATA, 0);
115                 if(len < 0 && (errno == EAGAIN || errno == EINTR)) {
116                     ALOGW("%s: vsync read: EAGAIN, retry (%d/%d).",
117                           __FUNCTION__, i, MAX_RETRY_COUNT);
118                     continue;
119                 } else {
120                     break;
121                 }
122             }
123 
124             if (len < 0) {
125                 ALOGE ("FATAL:%s:not able to read file:%s, %s", __FUNCTION__,
126                        vsync_timestamp_fb0, strerror(errno));
127                 close (fd_timestamp);
128                 fakevsync = true;
129             }
130 
131             // extract timestamp
132             const char *str = vdata;
133             if (!strncmp(str, "VSYNC=", strlen("VSYNC="))) {
134                 cur_timestamp = strtoull(str + strlen("VSYNC="), NULL, 0);
135             } else {
136                 ALOGE ("FATAL: %s: vsync timestamp not in correct format: [%s]",
137                        __FUNCTION__,
138                        str);
139                 fakevsync = true;
140             }
141 
142         } else {
143             usleep(16000);
144             cur_timestamp = systemTime();
145         }
146         // send timestamp to HAL
147         ALOGD_IF (VSYNC_DEBUG, "%s: timestamp %llu sent to HWC for %s",
148                   __FUNCTION__, cur_timestamp, "fb0");
149         ctx->proc->vsync(ctx->proc, dpy, cur_timestamp);
150 
151     } while (true);
152     if(fd_timestamp >= 0)
153         close (fd_timestamp);
154 
155     return NULL;
156 }
157 
init_vsync_thread(hwc_context_t * ctx)158 void init_vsync_thread(hwc_context_t* ctx)
159 {
160     int ret;
161     pthread_t vsync_thread;
162     ALOGI("Initializing VSYNC Thread");
163     ret = pthread_create(&vsync_thread, NULL, vsync_loop, (void*) ctx);
164     if (ret) {
165         ALOGE("%s: failed to create %s: %s", __FUNCTION__,
166               HWC_VSYNC_THREAD_NAME, strerror(ret));
167     }
168 }
169 
170 }; //namespace
171