hwc_vsync.cpp revision 6287ca3d8c0bc7bd6e18c729781ea1d03bb23034
1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * Copyright (C) 2012-2013, The Linux Foundation. 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#include <cutils/properties.h> 22#include <utils/Log.h> 23#include <fcntl.h> 24#include <sys/ioctl.h> 25#include <linux/msm_mdp.h> 26#include <sys/resource.h> 27#include <sys/prctl.h> 28#include <poll.h> 29#include "hwc_utils.h" 30#include "string.h" 31#include "external.h" 32 33namespace qhwc { 34 35#define HWC_VSYNC_THREAD_NAME "hwcVsyncThread" 36 37int hwc_vsync_control(hwc_context_t* ctx, int dpy, int enable) 38{ 39 int ret = 0; 40 if(!ctx->vstate.fakevsync && 41 ioctl(ctx->dpyAttr[dpy].fd, MSMFB_OVERLAY_VSYNC_CTRL, 42 &enable) < 0) { 43 ALOGE("%s: vsync control failed. Dpy=%d, enable=%d : %s", 44 __FUNCTION__, dpy, enable, strerror(errno)); 45 ret = -errno; 46 } 47 return ret; 48} 49 50static void *vsync_loop(void *param) 51{ 52 const char* vsync_timestamp_fb0 = "/sys/class/graphics/fb0/vsync_event"; 53 const char* vsync_timestamp_fb1 = "/sys/class/graphics/fb1/vsync_event"; 54 int dpy = HWC_DISPLAY_PRIMARY; 55 56 hwc_context_t * ctx = reinterpret_cast<hwc_context_t *>(param); 57 58 char thread_name[64] = HWC_VSYNC_THREAD_NAME; 59 prctl(PR_SET_NAME, (unsigned long) &thread_name, 0, 0, 0); 60 setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY + 61 android::PRIORITY_MORE_FAVORABLE); 62 63 const int MAX_DATA = 64; 64 static char vdata[MAX_DATA]; 65 struct pollfd pfd; 66 67 uint64_t cur_timestamp=0; 68 ssize_t len = -1; 69 int fb0_fd = -1; 70 int ret = 0; 71 bool fb1_vsync = false; 72 bool logvsync = false; 73 74 char property[PROPERTY_VALUE_MAX]; 75 if(property_get("debug.hwc.fakevsync", property, NULL) > 0) { 76 if(atoi(property) == 1) 77 ctx->vstate.fakevsync = true; 78 } 79 80 if(property_get("debug.hwc.logvsync", property, 0) > 0) { 81 if(atoi(property) == 1) 82 logvsync = true; 83 } 84 85 /* Currently read vsync timestamp from drivers 86 e.g. VSYNC=41800875994 87 */ 88 fb0_fd = open(vsync_timestamp_fb0, O_RDONLY); 89 pfd.fd = fb0_fd; 90 pfd.events = POLLPRI | POLLERR; 91 92 if (fb0_fd < 0) { 93 // Make sure fb device is opened before starting this thread so this 94 // never happens. 95 ALOGE ("FATAL:%s:not able to open file:%s, %s", __FUNCTION__, 96 (fb1_vsync) ? vsync_timestamp_fb1 : vsync_timestamp_fb0, 97 strerror(errno)); 98 ctx->vstate.fakevsync = true; 99 } 100 101 do { 102 if (LIKELY(!ctx->vstate.fakevsync)) { 103 int err = poll(&pfd, 1, -1); 104 if(err > 0) { 105 if (pfd.revents & POLLPRI) { 106 len = pread(fb0_fd, vdata, MAX_DATA, 0); 107 if (UNLIKELY(len < 0)) { 108 // If the read was just interrupted - it is not a fatal 109 // error. Just continue in this case 110 ALOGE ("FATAL:%s:not able to read file:%s, %s", 111 __FUNCTION__, 112 vsync_timestamp_fb0, strerror(errno)); 113 continue; 114 } 115 // extract timestamp 116 const char *str = vdata; 117 if (!strncmp(str, "VSYNC=", strlen("VSYNC="))) { 118 cur_timestamp = strtoull(str + strlen("VSYNC="), 119 NULL, 0); 120 } 121 } 122 } else { 123 ALOGE("%s: vsync poll failed errno: %s", __FUNCTION__, 124 strerror(errno)); 125 continue; 126 } 127 } else { 128 usleep(16666); 129 cur_timestamp = systemTime(); 130 } 131 // send timestamp to HAL 132 if(ctx->vstate.enable) { 133 ALOGD_IF (logvsync, "%s: timestamp %llu sent to HWC for %s", 134 __FUNCTION__, cur_timestamp, "fb0"); 135 ctx->proc->vsync(ctx->proc, dpy, cur_timestamp); 136 } 137 138 } while (true); 139 if(fb0_fd >= 0) 140 close (fb0_fd); 141 142 return NULL; 143} 144 145void init_vsync_thread(hwc_context_t* ctx) 146{ 147 int ret; 148 pthread_t vsync_thread; 149 ALOGI("Initializing VSYNC Thread"); 150 ret = pthread_create(&vsync_thread, NULL, vsync_loop, (void*) ctx); 151 if (ret) { 152 ALOGE("%s: failed to create %s: %s", __FUNCTION__, 153 HWC_VSYNC_THREAD_NAME, strerror(ret)); 154 } 155} 156 157}; //namespace 158