summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Brehm <djp952@gmail.com>2012-09-15 02:03:39 -0500
committerChirayu Desai <chirayudesai1@gmail.com>2012-09-16 11:36:05 +0530
commit3c938a7e18ab2e06b3d925fdc99e157ad125f6bb (patch)
treeac9d4a10ed930d51ce515b99e95625a8769d8a6d
parent317dcfa0f0ed518a7bb5577ea36559713c3f6698 (diff)
downloadandroid_hardware_samsung-3c938a7e18ab2e06b3d925fdc99e157ad125f6bb.tar.gz
android_hardware_samsung-3c938a7e18ab2e06b3d925fdc99e157ad125f6bb.tar.bz2
android_hardware_samsung-3c938a7e18ab2e06b3d925fdc99e157ad125f6bb.zip
exynos3: Implement custom VSYNC IOCTL
* Replace crespo-based VSYNC uevent mechanism in hwcomposer with a custom IOCTL mechanism instead (required kernel modifications. * The VSYNC uevents were spamming the Android UEventObserver and causing about 7% of constant CPU load c86856efabfa0b2981ceb47898dc5873a4998707 Improve custom VSYNC handler in hwcomposer * only poll when necessary * solves suspend/resume instability? 45bf1dae7fa9057a3415151f7559e7bd2a162ead Change-Id: Icdb5c60059e71688479d390b7b3a1f09a0315a5f
-rwxr-xr-xexynos3/s5pc110/include/sec_lcd.h1
-rw-r--r--exynos3/s5pc110/libhwcomposer/Android.mk4
-rw-r--r--exynos3/s5pc110/libhwcomposer/SecHWC.cpp52
3 files changed, 57 insertions, 0 deletions
diff --git a/exynos3/s5pc110/include/sec_lcd.h b/exynos3/s5pc110/include/sec_lcd.h
index 6a3a34a..82ef42f 100755
--- a/exynos3/s5pc110/include/sec_lcd.h
+++ b/exynos3/s5pc110/include/sec_lcd.h
@@ -34,6 +34,7 @@ struct secfb_user_window {
#define FBIO_WAITFORVSYNC _IO ('F', 32)
#define SECFB_WIN_POSITION _IOW ('F', 203, struct secfb_user_window)
#define S3CFB_SET_VSYNC_INT _IOW ('F', 206, uint32_t)
+#define S3CFB_WAIT_FOR_VSYNC _IOR ('F', 311, uint64_t)
#define DEFAULT_LCD_WIDTH (480)
#define DEFAULT_LCD_HEIGHT (800)
diff --git a/exynos3/s5pc110/libhwcomposer/Android.mk b/exynos3/s5pc110/libhwcomposer/Android.mk
index defda3e..a058145 100644
--- a/exynos3/s5pc110/libhwcomposer/Android.mk
+++ b/exynos3/s5pc110/libhwcomposer/Android.mk
@@ -27,6 +27,10 @@ LOCAL_C_INCLUDES := \
LOCAL_SRC_FILES := SecHWCUtils.cpp SecHWC.cpp
+ifeq ($(BOARD_CUSTOM_VSYNC_IOCTL),true)
+ LOCAL_CFLAGS += -DVSYNC_IOCTL
+endif
+
LOCAL_MODULE := hwcomposer.$(TARGET_BOARD_PLATFORM)
LOCAL_MODULE_TAGS := optional
include $(BUILD_SHARED_LIBRARY)
diff --git a/exynos3/s5pc110/libhwcomposer/SecHWC.cpp b/exynos3/s5pc110/libhwcomposer/SecHWC.cpp
index dda1108..31d25f4 100644
--- a/exynos3/s5pc110/libhwcomposer/SecHWC.cpp
+++ b/exynos3/s5pc110/libhwcomposer/SecHWC.cpp
@@ -453,6 +453,17 @@ static int hwc_query(struct hwc_composer_device* dev,
return 0;
}
+#ifdef VSYNC_IOCTL
+// Linux version of a manual reset event to control when
+// and when not to ask the video card for a VSYNC. This
+// stops the worker thread from asking for a VSYNC when
+// there is nothing useful to do with it and more closely
+// mimicks the original uevent mechanism
+int vsync_enable = 0;
+pthread_mutex_t vsync_mutex = PTHREAD_MUTEX_INITIALIZER;
+pthread_cond_t vsync_condition = PTHREAD_COND_INITIALIZER;
+#endif
+
static int hwc_eventControl(struct hwc_composer_device* dev,
int event, int enabled)
{
@@ -465,6 +476,18 @@ static int hwc_eventControl(struct hwc_composer_device* dev,
if (err < 0)
return -errno;
+#if VSYNC_IOCTL
+ // Enable or disable the ability for the worker thread
+ // to ask for VSYNC events from the video driver
+ pthread_mutex_lock(&vsync_mutex);
+ if(enabled) {
+ vsync_enable = 1;
+ pthread_cond_broadcast(&vsync_condition);
+ }
+ else vsync_enable = 0;
+ pthread_mutex_unlock(&vsync_mutex);
+#endif
+
return 0;
}
@@ -496,18 +519,47 @@ void handle_vsync_uevent(hwc_context_t *ctx, const char *buff, int len)
static void *hwc_vsync_thread(void *data)
{
hwc_context_t *ctx = (hwc_context_t *)(data);
+#ifdef VSYNC_IOCTL
+ uint64_t timestamp = 0;
+#else
char uevent_desc[4096];
memset(uevent_desc, 0, sizeof(uevent_desc));
+#endif
setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
+#ifndef VSYNC_IOCTL
uevent_init();
+#endif
while(true) {
+#ifdef VSYNC_IOCTL
+ // Only continue if hwc_eventControl is enabled, otherwise
+ // just sit here and wait until it is. This stops the code
+ // from constantly looking for the VSYNC event with the screen
+ // turned off.
+ pthread_mutex_lock(&vsync_mutex);
+ if(!vsync_enable) pthread_cond_wait(&vsync_condition, &vsync_mutex);
+ pthread_mutex_unlock(&vsync_mutex);
+
+ timestamp = 0; // Reset the timestamp value
+
+ // S3CFB_WAIT_FOR_VSYNC is a custom IOCTL I added to wait for
+ // the VSYNC interrupt, and then return the timestamp that was
+ // originally being communicated via a uevent. The uevent was
+ // spamming the UEventObserver and events/0 process with more
+ // information than this device could really deal with every 18ms
+ int res = ioctl(ctx->global_lcd_win.fd, S3CFB_WAIT_FOR_VSYNC, &timestamp);
+ if(res > 0) {
+ if(!ctx->procs || !ctx->procs->vsync) continue;
+ ctx->procs->vsync(ctx->procs, 0, timestamp);
+ }
+#else
int len = uevent_next_event(uevent_desc, sizeof(uevent_desc) - 2);
bool vsync = !strcmp(uevent_desc, "change@/devices/platform/s3cfb");
if(vsync)
handle_vsync_uevent(ctx, uevent_desc, len);
+#endif
}
return NULL;