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