From: Greg Hackmann <ghackmann@google.com> Date: Mon, 23 Jul 2012 22:31:10 +0000 (-0700) Subject: hwc: read vsync timestamps from sysfs X-Git-Tag: cm-10.1-M1~314 X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=2972485a91007a12d3ad1c6057601ccbf15f01ef;p=GitHub%2FLineageOS%2Fandroid_hardware_samsung_slsi_exynos5.git hwc: read vsync timestamps from sysfs Change-Id: Ife094105b247f4cfd2edb148a1914c50f62873b4 Signed-off-by: Greg Hackmann <ghackmann@google.com> --- diff --git a/libhwc/hwc.cpp b/libhwc/hwc.cpp index 1dcd320..d948f38 100644 --- a/libhwc/hwc.cpp +++ b/libhwc/hwc.cpp @@ -16,6 +16,7 @@ #include <errno.h> #include <fcntl.h> +#include <poll.h> #include <pthread.h> #include <stdio.h> #include <stdlib.h> @@ -72,6 +73,7 @@ struct exynos5_hwc_composer_device_1_t { hwc_composer_device_1_t base; int fd; + int vsync_fd; exynos5_hwc_post_data_t bufs; const private_module_t *gralloc_module; @@ -708,27 +710,23 @@ static void handle_hdmi_uevent(struct exynos5_hwc_composer_device_1_t *pdev, pdev->procs->invalidate(pdev->procs); } -static void handle_vsync_uevent(struct exynos5_hwc_composer_device_1_t *pdev, - const char *buff, int len) +static void handle_vsync_event(struct exynos5_hwc_composer_device_1_t *pdev) { - uint64_t timestamp = 0; - const char *s = buff; - if (!pdev->procs || !pdev->procs->vsync) return; - s += strlen(s) + 1; - - while (*s) { - if (!strncmp(s, "VSYNC=", strlen("VSYNC="))) - timestamp = strtoull(s + strlen("VSYNC="), NULL, 0); - - s += strlen(s) + 1; - if (s - buff >= len) - break; + char buf[4096]; + int err = read(pdev->vsync_fd, buf, sizeof(buf)); + if (err < 0) { + ALOGE("error reading vsync timestamp: %s", strerror(errno)); + return; } + buf[sizeof(buf) - 1] = '\0'; - pdev->procs->vsync(pdev->procs, 0, timestamp); + errno = 0; + uint64_t timestamp = strtoull(buf, NULL, 0); + if (!errno) + pdev->procs->vsync(pdev->procs, 0, timestamp); } static void *hwc_vsync_thread(void *data) @@ -741,19 +739,35 @@ static void *hwc_vsync_thread(void *data) setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY); uevent_init(); - while (true) { - int len = uevent_next_event(uevent_desc, - sizeof(uevent_desc) - 2); - bool vsync = !strcmp(uevent_desc, - "change@/devices/platform/exynos5-fb.1"); - if (vsync) - handle_vsync_uevent(pdev, uevent_desc, len); + struct pollfd fds[2]; + fds[0].fd = pdev->vsync_fd; + fds[0].events = POLLPRI; + fds[1].fd = uevent_get_fd(); + fds[1].events = POLLIN; + + while (true) { + int err = poll(fds, 2, -1); - bool hdmi = !strcmp(uevent_desc, - "change@/devices/virtual/switch/hdmi"); - if (hdmi) - handle_hdmi_uevent(pdev, uevent_desc, len); + if (err > 0) { + if (fds[0].revents & POLLPRI) { + handle_vsync_event(pdev); + } + else if (fds[1].revents & POLLIN) { + int len = uevent_next_event(uevent_desc, + sizeof(uevent_desc) - 2); + + bool hdmi = !strcmp(uevent_desc, + "change@/devices/virtual/switch/hdmi"); + if (hdmi) + handle_hdmi_uevent(pdev, uevent_desc, len); + } + } + else if (err == -1) { + if (errno == EINTR) + break; + ALOGE("error in vsync thread: %s", strerror(errno)); + } } return NULL; @@ -809,6 +823,13 @@ static int exynos5_open(const struct hw_module_t *module, const char *name, goto err_get_module; } + dev->vsync_fd = open("/sys/devices/platform/exynos5-fb.1/vsync", O_RDONLY); + if (dev->vsync_fd < 0) { + ALOGE("failed to open vsync attribute"); + ret = dev->vsync_fd; + goto err_ioctl; + } + sw_fd = open("/sys/class/switch/hdmi/state", O_RDONLY); if (sw_fd) { char val; @@ -835,11 +856,13 @@ static int exynos5_open(const struct hw_module_t *module, const char *name, if (ret) { ALOGE("failed to start vsync thread: %s", strerror(ret)); ret = -ret; - goto err_ioctl; + goto err_vsync; } return 0; +err_vsync: + close(dev->vsync_fd); err_ioctl: close(dev->fd); err_get_module: @@ -851,6 +874,9 @@ static int exynos5_close(hw_device_t *device) { struct exynos5_hwc_composer_device_1_t *dev = (struct exynos5_hwc_composer_device_1_t *)device; + pthread_kill(dev->vsync_thread, SIGTERM); + pthread_join(dev->vsync_thread, NULL); + close(dev->vsync_fd); close(dev->fd); return 0; }